Based on Ilya's response:
Find xml
.NET fallback locations (ignoring GAC and other irrelevant subdirectories)
static FileInfo GetXmlDocFile( Assembly assembly ) {
string assemblyDirPath = Path.GetDirectoryName( assembly.Location );
string fileName = Path.GetFileNameWithoutExtension( assembly.Location ) +".xml";
return GetFallbackDirectories( CultureInfo.CurrentCulture )
.Select( dirName => CombinePath( assemblyDirPath, dirName, fileName ) )
.Select( filePath => new FileInfo( filePath ) )
.Where( file => file.Exists )
.First( );
}
static IEnumerable<string> GetFallbackDirectories( CultureInfo culture ) {
return culture
.Enumerate( c => c.Parent.Name != c.Name ? c.Parent : null )
.Select( c => c.Name );
}
static IEnumerable<T> Enumerate<T>( this T start, Func<T, T> next ) {
for( T item = start; !object.Equals( item, default(T) ); item = next( item ) )
yield return item;
}
static string CombinePath( params string[] args ) {
return args.Aggregate( Path.Combine );
}
Find element
Processing XML Documentation
static XElement GetDocMember( XElement docMembers, MemberInfo member ) {
string memberId = GetMemberId( member );
return docMembers.Elements( "member" )
.Where( e => e.Attribute( "name" ).Value == memberId )
.First( );
}
static string GetMemberId( MemberInfo member ) {
char memberKindPrefix = GetMemberPrefix( member );
string memberName = GetMemberFullName( member );
return memberKindPrefix + ":" + memberName;
}
static char GetMemberPrefix( MemberInfo member ) {
return member.GetType( ).Name
.Replace( "Runtime", "" )[0];
}
static string GetMemberFullName( MemberInfo member ) {
string memberScope = "";
if( member.DeclaringType != null )
memberScope = GetMemberFullName( member.DeclaringType );
else if( member is Type )
memberScope = ((Type)member).Namespace;
return memberScope + "." + member.Name;
}
Example use
Type type = typeof( string );
var file = GetXmlDocFile( type.Assembly );
var docXml = XDocument.Load( file.FullName );
var docMembers = docXml.Root.Element( "members" );
var member = type.GetProperty( "Length" );
var docMember = GetDocMember( docMembers, member );