【问题标题】:.NET 2.0: Invoking Methods Using Reflection And Generics Causes Exception.NET 2.0:使用反射和泛型调用方法会导致异常
【发布时间】:2010-06-14 21:05:37
【问题描述】:

我是 Stack Overflow 的新手,请见谅。我刚刚开始过渡到 C#,但遇到了一个问题。

我想传入一个泛型类并从该类调用一个方法。所以,我的代码如下所示:

public void UpdateRecords<T>(T sender) where T : new() //where T: new() came from Resharper
{
    Type foo = Type.GetType(sender.GetType().ToString());
    object[] userParameters = new object[2];
    userParameters[0] = x;
    userParameters[1] = y;
    sender = new T(); //This was to see if I could solve my exception problem
    MethodInfo populateRecord = foo.GetMethod("MethodInOtherClass");
    populateMethod.Invoke(sender, userParameters);
}

抛出异常:“对象引用未设置为对象的实例。”

再次,我真的很抱歉,因为我对 C# 几乎是全新的,这是我第一次处理反射和泛型。谢谢!

【问题讨论】:

  • 异常到底是在哪里抛出的?

标签: c# .net generics reflection .net-2.0


【解决方案1】:

首先,我建议在调试器中运行此代码并打开一个“Break on Exception” 以帮助隔离导致错误的行。这是一种有用的调试技术,可以帮助您在将来更快地发现这些类型的问题。转到 VS 中的 Debug &gt;&gt; Exceptions 并选中 Thrown 列中的 Common Language Runtime Exceptions 复选框。

现在解决您的问题。 sender 很可能以 null 的形式传入。 如果是这样,则行:

Type foo = Type.GetType(sender.GetType().ToString()); 

将抛出一个NullReferenceException。相反,您可以使用:

Type foo = typeof(T); 

它标识通用参数的类型,而不需要它的实例。

现在,如果不了解您的代码试图做什么,就不可能说实例化T 的实例是否是正确的做法。 仅仅因为 ReSharper 建议添加 where T : new() 并不意味着它是合适的 - 除非您知道这是正确的行为

最后,我不知道是否有令人信服的理由使用反射来调用MethodInOtherClass - 也许有。但是由于您是 C# 新手,我会提到,如果类型 T 将始终是某个基本类型 A 的子类,或者将始终实现包含您要调用的方法的某个接口 I,您可以简单地应用一个通用约束来让编译器知道这一点。然后您可以调用该方法而无需恢复为使用反射:

public void UpdateRecords<T>(T sender) 
   where T : SomeBaseClass_Or_SomeInterface_ThatDefinesMethod
{
  sender = new T();
  sender.MethodInOtherClass( x, y );
}

好多了。

最后的评论。将参数传递给方法,然后完全忽略它是不寻常的 - 只是为了在方法中实例化一个实例。在某些情况下它是合适的——但我倾向于将其视为code smell。如果可能的话,我会尝试去掉 sender 参数,或者更改代码以首先测试它是否为空,然后再实例化。

【讨论】:

    【解决方案2】:

    sender.GetType().ToString() 返回类型名称没有程序集名称。

    Type.GetType 需要类型名称 程序集名称(除非该类型在执行程序集或 mscorlib 中)。如果找不到类型(例如,由于缺少程序集名称),则返回空引用。


    尝试将您的代码更改为

    Type foo = sender.GetType();
    

    甚至只是

    Type foo = typeof(T);
    

    【讨论】:

      【解决方案3】:

      你应该能够这样做来获取类型:

      Type foo = typeof(T);
      

      你没有指定你在哪里得到 NullReferenceException,但我想知道 foo 是否返回为 null...

      【讨论】:

        【解决方案4】:

        要么:

        1. sender 为空,因此 sender.GetType() 将失败。
        2. foo.GetMethod("MethodInOtherClass") 返回 null,所以 populateMethod.Invoke() 会失败。
        3. MethodInOtherClass 取决于某些先决条件(非空引用),因此当这些条件不存在时它将失败。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-27
          相关资源
          最近更新 更多