.NET Generics: Using an activator created as generic shows the wrong type? Need to bypass
Today I have a lot of problems. I'm sure it's simple, but ... Here's my sample code:
using System;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
public ArrayList SomeProp { get; set; }
static void Main(string[] args)
{
// Get the Type of a property by reflection.
Type myPropType = typeof(Program).GetProperty("SomeProp").PropertyType;
// Create an instance of the determined Type.
var x = Activator.CreateInstance(myPropType);
// Now try to use that instance, passing to a method that takes a generic.
WhatAmI(x);
Console.ReadKey();
}
private static void WhatAmI<T>(T x)
{
Console.WriteLine("T is: " + typeof(T).FullName);
Console.WriteLine("x is: " + x.GetType().FullName);
}
}
}
The output signal is here:
T is: System.Object
x is: System.Collections.ArrayList
Basically what happens here is I have some property in some class. It doesn't matter what / where it comes from. The important part is that I get the PropertyInfo for this property. From there I create a new instance of my type with an activator.
Now, if I pass this instantiated function that takes a generic parameter, the generic type is always encountered as Object, because Activator.CreateInstance () returns an object, so "var x" is an Object, not this case, ArrayList.
I need the generic type to be the actual type, in his case "ArrayList".
I know there is an Activator.CreateInstance () that I can use instead, but I cannot use the Type (PropertyInfo.PropertyType) in angle brackets for this method.
I could also just pass the returned object, like:
myPropType x = (myPropType)Activator.CreateInstance(myPropType);
But obviously it doesn't compile ... Plus it would be invalid anyway, because the cast time is compile time and I don't know the type before execution, but conceptually its what I need ...
So, I'm stuck with this type but can't figure out how to pass it to the WhatAmI () method and it has an ArrayList, not an Object.
Ideas?
source to share
To call common methods with help Type
at runtime, you need to use reflection in particular - and MakeGenericMethod
for example:
typeof(Program).GetMethod("WhatAmI",
BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(x.GetType()).Invoke(null, new object[] { x });
Otherwise, the compiler maps <T>
out the type of the variable - object
in this case.
One point is that you can improve the situation by only doing one reflection - that is, don't use Activator
, but use a general constraint instead:
private static void WhatAmI<T>() where T : new()
{
T x = new T();
Console.WriteLine("T is: " + typeof(T).FullName);
Console.WriteLine("x is: " + x.GetType().FullName);
}
Defines a method without arg, but with a default constructor; then:
// Get the Type of a property by reflection.
Type myPropType = typeof(Program).GetProperty("SomeProp").PropertyType;
// Now call a generic method just using the type
typeof(Program).GetMethod("WhatAmI",
BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(myPropType).Invoke(null, null);
calls a method using only the type - an instance is created inside the method. This is usually faster than repeated reflections.
source to share