【问题标题】:Using a Type object to create a generic使用 Type 对象创建泛型
【发布时间】:2010-03-29 20:50:14
【问题描述】:

我正在尝试使用 Type 对象创建一个泛型类的实例。

基本上,我将在运行时收集不同类型的对象,并且由于无法确定它们究竟是什么类型,我认为我将不得不使用反射。

我正在研究类似的东西:

Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);

这很好。 ^___^

问题是,我想访问我的 GenericType 实例的方法,但我不能,因为它是作为对象类输入的。我找不到将 obj 转换为特定 GenericType 的方法,因为这首先是问题所在(即,我不能放入类似的东西:)

((GenericType<elType>)obj).MyMethod();

应该如何解决这个问题?

非常感谢! ^___^

【问题讨论】:

标签: c# .net generics reflection


【解决方案1】:

你必须继续使用反射来调用实际的方法:

// Your code
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);

// To execute the method
MethodInfo method = genType.GetMethod("MyMethod",
    BindingFlags.Instance | BindingFlags.Public);
method.Invoke(obj, null);

有关详细信息,请参阅Type.GetMethodMethodBase.Invoke

【讨论】:

  • @Richard Neil Ilagan:嗯...有一些运气。下个月(ish)Microsoft 发布 VS 2010 和 .NET 4。当发生这种情况时,您将能够完全按照您在问题中所写的内容进行操作;我在回答中提到的dynamic 关键字将在运行时而不是编译时绑定到方法(这意味着如果方法不存在,您将在运行时得到异常,而不是编译器错误)。您可以使用 VS2010 的发布候选者现在免费使用 .NET 4。
  • 也许您也会对 Fasterflect (fasterflect.codeplex.com) 感兴趣。它是一个旨在通过代码生成使反射更容易使用和更快的库。让你做一些简洁的事情,比如在给定一组参数以及更基本的东西的情况下调用最佳重载匹配。
  • @Randolpho ~ 是的!实际上,我也对 .NET4 的这一方面感到有点兴奋。希望我们能够从一开始就迁移我们的应用程序! :) @Morten ~ 非常感谢!那肯定会成为我的帮助代码库。 :)
【解决方案2】:

一旦你开始了反思游戏,你就必须一直玩到最后。该类型在编译时未知,因此您无法强制转换它。您必须通过反射调用该方法:

obj.GetType().InvokeMember(
    "MyMethod", 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, 
    null, 
    obj, 
    null
);

【讨论】:

  • +1。喜欢第一行。你必须一直玩到最后,伙计。 edit 另外,我刚刚输掉了比赛。
【解决方案3】:

在 C# 3.5 中,您必须使用 Type.GetMethodMethodInfo.Invoke 来调用该方法。

在 C# 4 中,您可以使用 dynamic 关键字并在运行时绑定到方法。

【讨论】:

    【解决方案4】:

    最直接的方法是从 GenericType 中提取非泛型超类型(基类或接口),其中包含您要为此目的公开的方法:

    class GenericType<T> : GenericBase { ... }
    class GenericBase { abstract void MyMethod(); }
    

    如果做不到这一点,请按照@Aaronaught 的建议使用反射来访问方法本身。

    【讨论】:

      【解决方案5】:

      创建实例后,只需执行以下操作:

      MethodInfo method = genType.GetMethod("MyMethod");
      method.Invoke(obj, null);
      

      【讨论】:

        【解决方案6】:

        如果您知道要调用的方法的签名,您不仅可以使用MethodInfo.Invoke(),如此处其他示例所示,还可以创建一个允许更有效调用的委托(如果您需要调用相同的方法多次)使用Delegate.CreateDelegate()

        【讨论】:

          【解决方案7】:

          我不确定您的类型有多少变化,或者您是否可以控制您将在其中调用的方法,但创建一个定义您将要使用的一组函数的接口可能会很有用打电话。所以创建实例后,你可以强制转换为接口并调用你需要的任何函数。

          所以创建你的标准接口(如果你可以控制它们,你需要在每种类型中实现它):

          interface IMyInterface
          {
             void A();
             int  B();
          }
          
          class One : IMyInterface
          {
             ...
             implement A and B
             ...
          }
          
          Type elType = Type.GetType(obj);
          Type genType = typeof(GenericType<>).MakeGenericType(elType);
          IMyInterface obj = (IMyInterface)Activator.CreateInstance(genType);
          obj.A();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-21
            • 2014-04-04
            • 1970-01-01
            • 1970-01-01
            • 2012-03-13
            • 1970-01-01
            • 2021-10-10
            • 1970-01-01
            相关资源
            最近更新 更多