简体   繁体   中英

Construct a generic type through reflection given the type of another object

I'm passing a type to a method and creating an object based on that type. Assume argType is a Type and passed to the method as a parameter.

var assembly = AppDomain.CurrentDomain.GetAssemblies().Single(a => a.GetName().Name == "MyAssembly");
var newType = assembly.GetTypes().SingleOrDefault(x => x.FullName == argType.FullName + "Suffix");
var newObject = Activator.CreateInstance(newType);

This works fine for most objects, but if I pass a type with a generic sub type (eg MyClass<MyType> ), it fails [Assume the goal is to set newObject to a MyClassSuffix<MyType> ].

How could the code above be improved so that generic types (ending with "Suffix") can also be created? I looked at the FullName property for such types which contain substrings like '1[[ . I'd rather not do regex parsing to append "Suffix" before these characters begin. I'm thinking there is a better way.

You can use MakeGenericType method if you have instance of both types ie the generic class and the generic type parameter :

// assuming you have a generic class named Class<> 
// taking one generic type parameter
Type generic = typeof(MyClassSuffix<>);
Type typeParameter = typeof(MyClass);
Type genericInstance = generic.MakeGenericType(typeParameter);

and then:

object o = Activator.CreateInstance(genericInstance);

In your case you have generic as newType and you would need to figure out which type you need to pass as type parameter and it should work.

Read the following MSDN docs for detailed instructions on this topic:

https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/how-to-examine-and-instantiate-generic-types-with-reflection

UDPATE:

You can get generic type parameters too following way

    var newType = assembly.GetTypes().SingleOrDefault(x => x.FullName == argType.FullName + "Suffix");
     if(newType.IsGenericType)
     {
        // Get the generic type parameters or type arguments.
        Type[] typeParameters = t.GetGenericArguments();

        // Construct the type Dictionary<String, Example>.
        Type constructed = newType.MakeGenericType(typeParameters);
     }

If you are having a closed type then you can instantiate it same way like a normal class. See the following example:

public class GenericClass<Int>
{

}

Now we can generate an instance of it like:

 Type t = typeof(GenericClass<int>);
 object o = Activator.CreateInstance(y);
 Console.WriteLine(o);

DEMO Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM