.NET泛型:使用Activator创建的类型作为泛型显示错误类型?需要解决方法 [英] .NET Generics: Using an Activator created type as a generic shows wrong Type? Need workaround

查看:121
本文介绍了.NET泛型:使用Activator创建的类型作为泛型显示错误类型?需要解决方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天真的让我很难过。我确信它很简单,但是......这里是我的示例代码:

  using System; 
使用System.Collections;

namespace ConsoleApplication1
{
class Program
{
public ArrayList SomeProp {get;组; }

static void Main(string [] args)
{
//通过反射获取属性的类型。
键入myPropType = typeof(Program).GetProperty(SomeProp)。PropertyType;

//创建一个确定类型的实例。
var x = Activator.CreateInstance(myPropType);

//现在尝试使用该实例,传递给一个通用的方法。
WhatAmI(x);

Console.ReadKey();

$ b private static void WhatAmI< T>(T x)
{
Console.WriteLine(T is:+ typeof(T).FullName) ;
Console.WriteLine(x is:+ x.GetType()。FullName);



code
$ b

这里的输出是: / p>

  T是:System.Object 
x是:System.Collections.ArrayList

基本上这里发生的是我在某个类上有一些属性。它来自哪里/哪里并不重要。重要的部分是我得到该属性的PropertyInfo。从那里开始,我创建了一个类型为Activator的新实例。



现在,如果我将创建的实例传递给一个带泛型参数的函数,作为Object,因为Activator.CreateInstance()返回一个Object,所以var x是一个Object,在这种情况下不是一个ArrayList。



我需要我知道有一个Activator.CreateInstance(),我可以用它来代替,但是我们可以使用Activator.CreateInstance()方法,但我不能在该方法的尖括号内使用Type(PropertyInfo.PropertyType)。



我也可以投射返回的对象,如:

  myPropType x =(myPropType)Activator.CreateInstance(myPropType); 

但显然这不会编译...加上它无效,因为演员是编译时,我不知道类型,直到运行时,但在概念上它是我需要的... ...

因此我坚持这种类型,但我无法弄清楚如何将它传递给WhatAmI()方法,并且让T为ArrayList,而不是Object。



想法?

$ b在运行时使用类型调用泛型方法时,需要使用反射 - 和 code> MakeGenericMethod
尤其如下:

  typeof(Program).GetMethod WhatAmI,
BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(x.GetType())。Invoke(null,new object [] {x});

否则,编译器推断< T> 从变量类型 - object 在这种情况下。



这里的一个要点是可以改进通过只做反射一次 - 即不要使用 Activator ,而是使用通用约束:



pre $ private $ static void WhatAmI< T>()其中T:new()
{
T x = new T();
Console.WriteLine(T is:+ typeof(T).FullName);
Console.WriteLine(x is:+ x.GetType()。FullName);

定义不带 arg的方法一个默认的构造函数;然后:

  // //通过反射获取属性的类型。 
键入myPropType = typeof(Program).GetProperty(SomeProp)。PropertyType;

//现在调用一个只使用类型
的泛型方法typeof(Program).GetMethod(WhatAmI,
BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(myPropType).Invoke(null,null);

仅使用该类型调用方法 - 实例在内创建方法。这通常比反复反射快。


This really has my stumped today. I'm sure its simple, but... Here is 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 here is:

T is: System.Object
x is: System.Collections.ArrayList

Basically what is going on here is I have some property on some class. It doesnt really matter what/where that comes from. The important part is that I get the PropertyInfo for that property. From there I create a new instance of its Type with Activator.

Now If I pass that created instance to a function that takes a generic parameter, the generic Type always comes across as Object, because Activator.CreateInstance() returns an Object, so "var x" is an Object, not, in this case, an ArrayList.

What I need to happen is for the generic type to be the actual type, int his case "ArrayList".

I know there is an Activator.CreateInstance() that I can use instead, but I can't use a Type (PropertyInfo.PropertyType) within the angle brackets for that method.

I could also just cast the returned object, like:

myPropType x = (myPropType)Activator.CreateInstance(myPropType);

But obviously that doesn't compile... Plus it wouldn't be valid anyway because the cast is compile time, and I don't know the type until runtime, but conceptually its what I need...

So I'm stuck with this Type, but I can't figure out how to get it passed over to the WhatAmI() method, and have T be ArrayList, not Object.

Ideas?

解决方案

To call generic methods using a Type at runtime, you need to use reflection - and MakeGenericMethod in particular, something like:

typeof(Program).GetMethod("WhatAmI",
    BindingFlags.Static | BindingFlags.NonPublic)
    .MakeGenericMethod(x.GetType()).Invoke(null, new object[] { x });

Otherwise, the compiler infers the <T> from the variable type - object in this case.

One side point here is that you can improve things by only doing the reflection once - i.e. don't use Activator, but use a generic 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 the method without an 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 the method just using the type - the instance is created inside the method. This is usually faster than repeated reflection.

这篇关于.NET泛型:使用Activator创建的类型作为泛型显示错误类型?需要解决方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆