Create open constructed type from string

c#, system.reflection

Solution

You can get `T` using strings, you do it by calling `GetType` with the string name of `MyClass` and then getting the generic arguments of the resulting type. From there you can build up the other open generic types using `MakeGenericType`. You have to work from the inside out by constructing the most nested types first. To do it automatically across differing methods would require some string parsing to get to the nested types. For the sake of comparing .Net methods against Cecil methods, @Tengiz might have a better approach.

To run the code, update the string name of `MyClass` to have the correct namespace for your environment.

private static void Main(string[] args) {
    // change 'yournamespace'
    Type testType = Type.GetType("yournamespace.MyClass`1");
    Type[] testTypeGenericArgs = testType.GetGenericArguments();

    // Get T type from MyClass generic args
    Type tType = testTypeGenericArgs[0];

    Type genericListType = Type.GetType("System.Collections.Generic.List`1");

    // create type List<T>
    Type openListType = genericListType.MakeGenericType(testTypeGenericArgs[0]);
    Type genericTuple = Type.GetType("System.Tuple`2");
    Type stringType = Type.GetType("System.String");

    // create type Tuple<T, string>
    Type openTuple = genericTuple.MakeGenericType(new[] { tType, stringType });

    // create type List<Tuple<T, string>>
    Type openListOfTuple = genericListType.MakeGenericType(openTuple);

    Type[] typesFromStrings = new[] { tType, openListType, openListOfTuple };

    // get method parameters per example
    Type myClassType = typeof(MyClass<>);
    MethodInfo myMethodInfo = myClassType.GetMethod("MyMethod");
    Type[] paramTypes = myMethodInfo.GetParameters().Select(pi => pi.ParameterType).ToArray();

    // compare type created from strings against types
    // retrieved by reflection
    for (int i = 0; i < typesFromStrings.Length; i++) {
        Console.WriteLine(typesFromStrings[i].Equals(paramTypes[i]));
    }

    Console.ReadLine();
}

Problem

Let's say I have the following class. ``` MyClass<T> { public void MyMethod(T a, List<T> b, List<Tuple<T, string>> c) {} } ``` I can get the type of the arguments of the method as follow ``` Type testType = typeof(MyClass<>); MethodInfo myMethodInfo = testType.GetMethod("MyMethod"); Type[] paramTypes = myMethodInfo.GetParameters().Select(pi => pi.ParameterType); ``` How can I manually create an array containing the same open types as `paramTypes` from a string? For ex from ``` var typesAsStr = new string[] {"T", "List`1[T]", "List`1[Tuple`2[T, string]]"}; ``` If I had `MyClass<int>`, I could do something like `Type.GetType(fullQualifiedNameOfArg)` for each argument, but here I want to keep the generic argument T: - I can't create "a": I can't do `Type.GetType("T")` - I can almost create "b": I can do `Type.GetType("List` ``1")`, but the info on "T" is not yet present - I don't know how to create "c" I ended up needing this when converting a Mono.Cecil type into a .net type: Cecil gives me the info on a method named `"MyMethod"` with arguments `"T"`, `"List<T>"` and `"List<Tuple<T, string>>"`. I then want to get that method using reflection (if there are several methods with the same name and argument numbers, I have to check the args to know which one it is), that's why I'd want to have a way to transform what Cecil tells me into what .Net knows, to be able to compare with what's in `paramTypes`. I've also seen several other people asking how to convert a Mono.Cecil type into a .Net one, so that's also why I thought I'd try.

Original source