这是个虫子吗?访问以0为参数的专用静态方法时出现MissingMethodException

本文关键字:专用 参数 静态方法 MissingMethodException 访问 | 更新日期: 2023-09-27 18:20:31

我不确定是否应该在这里问这个问题,但现在我们开始了,在单元测试一个参数为short的私有静态方法时,只有当这个参数为0时,我才会得到MissingMethodException。

我使用的是针对Framework 4的VS 2010 SP1(完整版),以下是重现此错误的最低限度代码(我们正在升级VB6代码,所以不要粗鲁):

    [DataContract]
  public enum NotificationResult
  {
    [EnumMember]
    Success,
    [EnumMember]
    StoredError,
    [EnumMember]
    InvalidId,
    [EnumMember]
    OperationError,
  }
    public sealed class NotificationContext
  {
    private static NotificationResult GetExecuteResult(short result)
    {
      NotificationResult executeResult;
      switch (result)
      {
        case 0:
          executeResult = NotificationResult.Success;
          break;
        case 1:
          executeResult = NotificationResult.StoredError;
          break;
        case 2:
          executeResult = NotificationResult.InvalidId;
          break;
        default:
          executeResult = NotificationResult.OperationError;
          break;
      }
      return executeResult;
    }
  }

以下是我测试代码的方式:

 PrivateType privateHelperType = new PrivateType(typeof(NotificationContext));
      var actual = (NotificationResult)privateHelperType.InvokeStatic(
        "GetExecuteResult", (short)1);
      var actual2 = (NotificationResult)privateHelperType.InvokeStatic(
        "GetExecuteResult", (short)0); //here is where i get the exception

在第一次调用中,我得到了预期的结果,在第二次调用中我得到了异常(我将强制转换添加到short中,认为异常可能是因为它没有找到一个以int为参数的方法)。

有人能再现这种行为吗?,我做错什么了吗?

谢谢你的帮助。

这是个虫子吗?访问以0为参数的专用静态方法时出现MissingMethodException

问题是这个方法有两个重载(还有其他重载,但它们在这里无关紧要):

  • public Object InvokeStatic(string name, params Object[] args)
  • public Object InvokeStatic(string name, BindingFlags invokeAttr, params Object[] args)

不同之处在于,第二过载具有类型为BindingFlags的参数,该参数是enum。当您传递文字0作为第二个参数时,会选择此重载,因为文字0可以隐式转换为任何enum,并且不使用params被认为比在重载解析中使用它更好。所以,基本上

  • privateType.InvokeStatic("GetExecuteResult", 1)编译为privateType.InvokeStatic("GetExecuteResult", new object[] { 1 })
  • privateType.InvokeStatic("GetExecuteResult", 0)编译为privateType.InvokeStatic("GetExecuteResult", 0, new object[] { })

这就是你问题的原因。我认为避免这种情况的最干净的方法是显式创建数组:

privateType.InvokeStatic("GetExecuteResult", new object[] { 0 })

除了在代码中没有将文本0传递给方法之外,您可以先进行强制转换。根据规范,在这种情况下不应选择BindingFlags过载。但像这样的错误是一个已知的错误,不会被修复,因为它会破坏一些正在运行的程序。

有趣。。。我能够复制它,我找到了修复它的方法

short s = 0;
var actual2 = (NotificationResult)privateHelperType.InvokeStatic(
        "GetExecuteResult", s);

我会尽量让你的类不密封。这纯粹是猜测,但可能是将NotificationContext子类化为PrivateType的一部分。

我的第二个建议是下载类似dotpeek的东西:http://blogs.jetbrains.com/dotnet/2011/05/free-net-decompiler-is-available-for-early-access/看看PrivateType是什么样子的。了解它是如何运作的将有助于弄清实际发生了什么。