.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?

+1


source to share


1 answer


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.

+7


source







All Articles