How do create a Generic Object using Reflection

.net-4.5, c#, generics, reflection

Solution

In order to instantiate a generic type, you need to know the actual values (types) that should be substituted for its type parameters. The `GetGenericArguments()` method, being a form of reflection, only gives you the type arguments, not their actual values. The values are up to you... that is the entire point of generics.

If `item` is a type like `List<T>` then `item.GetGenericArguments()` will return an array containing a fake "type" representing the type parameter `T` (with its `IsGenericParameter` property set to true). Therefore, passing that parameter type back into `item.MakeGenericType()` will simply create another open generic type equivalent to the original. To close the generic type so that it can be instantiated you need to provide an actual (non-parameter) type argument, such as `int`.

For example, `typeof(List<>).MakeGenericType(typeof(int))` will return `typeof(List<int>)`, while `typeof(List<>).MakeGenericType(typeof(List<>).GetGenericArguments())` will simply return `typeof(List<>)` again. This is what is happening in your code.

I'm sorry if that is a bit opaque, I don't know how else to explain it. The bottom line is that a type like `List<T>` is only useful if you have a type you want to substitute in place of `T`.

Problem

First let me say, that what I want to do is get the value of a property in a generic class that may be overriden by class that inherits from it. Think of it in the base class as a default value, that the inheritor of the class can override to set their own Default value. I have tried to use reflection directly on the type, using the System.Reflection.FieldInfo.GetValue but this does not work for classes with generic types. So I think that I need to instantiate the class to be able to see what the value is. The "types" I have I retrieved by reading the Dlls in the bin and using Reflection to find the types that inherit from my interface. I am using .NET 4.5 here is documentation that seems like it explains exactly what I need to do http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx In this documentation the only difference I can see is how we got our types, I looked in the bin for types and they simply called typeof(), Since types are so complex it seems this may be a likely mis-match but I cannot see what is missing(if anything) ``` foreach (var item in types) { var ts = item.GetField("DefaultTimeToExpire"); Type[] typeArguments = item.GetGenericArguments(); if (ts != null) { var t = item.MakeGenericType(typeArguments); var obj = Activator.CreateInstance(t); var timespan = obj.DefaultTimeToExpire; subscriberInfos.Add(new Tuple<string, Type, TimeSpan>(item.Name, item, timespan)); } } ``` I am calling GetField to look for Items that have a field "DefaultTimeToExpire" so far this part works well to find the type I need. Next I call GetGenericArguments which returns an expected array of the type Arguments. then I call MakeGenericType and finally Create instance wich gives me the error message "Cannot create an instance of BusinessLogic.TestSubscriberXXX`1[Message] because Type.ContainsGenericParameters is true." This looks like exactly what I am supposed to do. Thanks

Original source