WillC
WillC

Reputation: 2125

Generic Way to Get MethodInfo For Methods Using Xml Documentation Member.Name

I am trying to get the System.Reflection.MethodInfo metadata of a method using the member name from an Xml Documentation file entry.

Here is the basic code. I have left out the boilerplate to get the values from the Member.name string for brevity.

// The following variables are all parsed out of the 'name' string from the 
// XML documentation for each entry (from 1st example below):
// Member: "ToInt"
// Namespace: "Library.Extensions"
// ClassName: "ConvertExtensions"    
// AssemblyToDocument: Library 
// ParameterArray: "System.String,System.Int32"

// Uses the GetMethod() method with the parameter 'types' overload
// as there can be multiple signatures for a particular Method name.  

string typeName = $"{Namespace}.{ClassName}, {AssemblyToDocument}";        
var types = ToTypeArray(ParameterArray);
MethodInfo methodInfo =  typeName.GetMethod(Member, types);


private Type[] ToTypeArray(string[] typeNames)
{
    var types = new List<Type>();

    foreach (string name in typeNames)
    {
        types.Add(Type.GetType(name));
    }
    return types.ToArray();
}

This works fine for methods with only one signature or with a few simple signatures like below.

<member name="M:Library.Extensions.ConvertExtensions.ToInt(System.String,System.Int32)"></member>

<member name="M:Library.Extensions.ConvertExtensions.ToBool(System.String)"></member>

But breaks down for more complicated examples, such as an method overloads. The strings from the doc XML for the more complicated types are just not parsable by Type.GetType(string).

<member name="M:Library.Extensions.ConvertExtensions.ToBool(System.String,System.String,System.Boolean)"></member>

<member name="M:Library.Extensions.IEnumerableExtensions.ElementInOrDefault``1(System.Collections.Generic.IEnumerable{``0},System.Int32)"></member>

Currently, I can get the MemberInfo for about half of the entries in my xml documentation file.

Is there a reliable, generic way to get the MethodInfo object using the member.name from an XML document file?

Upvotes: 0

Views: 424

Answers (1)

Alfred Luu
Alfred Luu

Reputation: 2028

This topic might be clearer as How to get MethodInfo with many overloading functions and complicated parameter.

I'm assuming that you did parsed XML documentation successful and got the string like this

NetCoreScripts.StackOverFlow.ReflectionTopic.MyObject(System.String,System.String,System.Boolean)

Over there you can use any separator method to split into 2 elements:

First is: NetCoreScripts.StackOverFlow.ReflectionTopic.MyObject

Second is array of: System.String, System.String, System.Boolean (3 params must be the same order)

    private static Type[] ToTypeArray(string[] typeNames)
    {
        var types = new List<Type>();

        foreach (string name in typeNames)
        {
            types.Add(Type.GetType(name));
        }

        return types.ToArray();
    }

I reuse your ToTypeArray and create a model

namespace NetCoreScripts.StackOverFlow.ReflectionTopic
{
    public class MyObject
    {
        public void DoMore(int parameter) { }
        public void DoMore(string str1, string str2, bool bool1) { }
        public void DoMore(string str, int num) { }
        public void DoMore(List<string> parameter) { }
        public void DoMore(List<string> parameter, int param) { }
        public void DoMore(List<List<string>> parameter, bool? nullableBool, bool isTrue) { }
    }
}

Main calling method will be

    public static void GetMyMethod(Type type, string[] arr)
    {
        var parameters = ToTypeArray(arr);
        var method = type.GetMethod("DoMore", parameters);
        Console.WriteLine(method.Name);
    }

    public static void MainFunc()
    {
        var type = Type.GetType("NetCoreScripts.StackOverFlow.ReflectionTopic.MyObject");
        GetMyMethod(type, new string[] { "System.Int32" });
        GetMyMethod(type, new string[] { "System.String", "System.String", "System.Boolean" });
        GetMyMethod(type, new string[] { "System.String", "System.Int32" });
        GetMyMethod(type, new string[] { "System.Collections.Generic.List`1[[System.String]]" });
        GetMyMethod(type, new string[] { "System.Collections.Generic.List`1[[System.String]]", "System.Int32" });
        GetMyMethod(type, new string[] { "System.Collections.Generic.List`1[[System.Collections.Generic.List`1[[System.String]]]]", "System.Nullable`1[[System.Boolean]]", "System.Boolean" });
    }

To know exactly there name, I suggest using full name on pair testing, write and read Xml would be easier

        Console.WriteLine(typeof(bool?).FullName); 
        //System.Nullable`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

        Console.WriteLine(Type.GetType("System.Nullable`1[[System.Boolean]]").FullName);
        //For shorter

Hope it helps

Upvotes: 0

Related Questions