How to get MethodInfo for open generic type from MethodInfo of closed type

The key seems to be Type.ContainsGenericParameters on the parameter type:

Given

public class MyClass<T>
{
    public void Foo(T t)
    {
    }

    public void Bar(int i)
    {

    }
}

Then

class Program
{
    static void Main(string[] args)
    {
        var obj = new MyClass<int>();

        // Closed type
        var closedType = obj.GetType();

        // Open generic (typeof(MyClass<>))
        var openType = closedType.GetGenericTypeDefinition();

        // Methods on open type
        var fooT = openType.GetMethod("Foo");
        var barint = openType.GetMethod("Bar");

        // Parameter types
        var tInFoo = fooT.GetParameters()[0].ParameterType;
        var iInBar = barint.GetParameters()[0].ParameterType;

        // Are they generic?
        var tInFooIsGeneric = tInFoo.ContainsGenericParameters;
        var iInBarIsGeneric = iInBar.ContainsGenericParameters;

        Console.WriteLine(tInFooIsGeneric);
        Console.WriteLine(iInBarIsGeneric);

        Console.ReadKey();
    }
}

outputs

True
False

This will obviously need more work for overloads and so on.


Could you get the definition of the generic class through Type.GetGenericTypeDefinition Method and find there the definition for the same method, say, by name (and the signature), and then compare Foo(T t) and Foo(int t):

MyClass<int> c = new MyClass<int>();

Type concreteType = c.GetType();
Console.Write("Concrete type name:");
Console.WriteLine(concreteType.FullName);
Console.WriteLine();

MethodInfo concreteMethod = concreteType.GetMethod("Foo");
if (concreteMethod != null)
{
    Console.WriteLine(concreteMethod.Name);
    foreach (ParameterInfo pinfo in concreteMethod.GetParameters())
    {
        Console.WriteLine(pinfo.Name);
        Console.WriteLine(pinfo.ParameterType);
        Console.WriteLine();
    }
    Console.WriteLine();
}

if (concreteType.IsGenericType)
{
    Console.Write("Generic type name:");
    Type genericType = concreteType.GetGenericTypeDefinition();
    Console.WriteLine(genericType.FullName);
    Console.WriteLine();

    MethodInfo genericMethod = genericType.GetMethod("Foo");
    if (genericMethod != null)
    {
        Console.WriteLine(genericMethod.Name);
        foreach (ParameterInfo pinfo in genericMethod.GetParameters())
        {
            Console.WriteLine(pinfo.Name);
            Console.WriteLine(pinfo.ParameterType);
            Console.WriteLine();
        }
        Console.WriteLine();
    }
}

I don't know if you have considered using Mono.Cecil instead of .Net's reflection.

// Gets the AssemblyDefinition (similar to .Net's Assembly).
Type testType = typeof(MyClass<>);
AssemblyDefinition assemblyDef = AssemblyDefinition.ReadAssembly(new Uri(testType.Assembly.CodeBase).LocalPath);
// Gets the TypeDefinition (similar to .Net's Type).
TypeDefinition classDef = assemblyDef.MainModule.Types.Single(typeDef => typeDef.Name == testType.Name);
// Gets the MethodDefinition (similar to .Net's MethodInfo).
MethodDefinition myMethodDef = classDef.Methods.Single(methDef => methDef.Name == "Foo");

then myMethodDef.FullName returns

"System.Void MyNamespace.MyClass`1::Foo(System.Int32,T,System.String)"

and classDef.GenericParameters[0].FullName returns

"T"

Note that Mono.Cecil uses a different way of writing generics, nested classes and arrays:

List[T] => List<T>
MyClass+MyNestedClass => MyClass/MyNestedClass
int[,] => int[0...,0...]