反射说接口方法在实现的类型中是虚拟的,但它们不是吗?

发布于 2024-10-14 18:27:52 字数 1003 浏览 3 评论 0原文

我在单元测试中有以下代码

    public bool TestMethodsOf<T, I>()
  {
   var impl = typeof(T);
   var valid = true;

   foreach (var iface in impl.GetInterfaces().Where(i => typeof(I).IsAssignableFrom(i)))
   {

    var members = iface.GetMethods();

    foreach (var member in members)
    {
     Trace.Write("Checking if method " + iface.Name + "." + member.Name + " is virtual...");
     var implMember = impl.GetMethod(member.Name, member.GetParameters().Select(c => c.ParameterType).ToArray());
     if (!implMember.IsVirtual)
     {
      Trace.WriteLine(string.Format("FAILED"));
      valid = false;
      continue;
     }

     Trace.WriteLine(string.Format("OK"));
    }
   }
   return valid;
  }

Assert.IsTrue(TestMethodsOf<MyView, IMyView>());

我想确保接口中的所有方法都声明为虚拟方法。原因是因为我正在应用 spring.net 方面,并且它仅适用于虚拟方法。

我遇到的问题是 implMember.IsVirtual 始终为 true,即使它们没有在声明类型中如此声明。

我的 TestMethodsOf 逻辑有什么问题?

干杯

I have the following code in an unit test

    public bool TestMethodsOf<T, I>()
  {
   var impl = typeof(T);
   var valid = true;

   foreach (var iface in impl.GetInterfaces().Where(i => typeof(I).IsAssignableFrom(i)))
   {

    var members = iface.GetMethods();

    foreach (var member in members)
    {
     Trace.Write("Checking if method " + iface.Name + "." + member.Name + " is virtual...");
     var implMember = impl.GetMethod(member.Name, member.GetParameters().Select(c => c.ParameterType).ToArray());
     if (!implMember.IsVirtual)
     {
      Trace.WriteLine(string.Format("FAILED"));
      valid = false;
      continue;
     }

     Trace.WriteLine(string.Format("OK"));
    }
   }
   return valid;
  }

which I call by

Assert.IsTrue(TestMethodsOf<MyView, IMyView>());

I want to ensure that all the methods from the interface are declared as virtual. The reason is because I'm applying a spring.net aspect and it will only apply to virtual methods.

The problem I'm having is that implMember.IsVirtual is always true, even when they are not declared as so in the declaring type.

What is wrong with my TestMethodsOf logic?

Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冧九 2024-10-21 18:27:52

所有在接口中声明的方法都被标记为virtualabstract,所有在类中实现接口方法的方法都被标记为virtualfinal,因此CLR知道它不能只是直接调用它们 - 它必须在运行时进行 vtable 查找才能调用正确的实现。接口实现仍然是虚拟的,但您不能覆盖它们,因为它们是最终的。

例如,以下 C# 定义:

public interface IInterface {
    void Method();
}

public class Class : IInterface {
    public void Method() {}
}

编译为以下 IL:

.class public interface abstract IInterface {
    .method public abstract virtual instance void Method() {}
}

.class public Class extends [mscorlib]System.Object implements IInterface {
    .method public specialname rtspecialname instance void .ctor() {}
    .method public virtual final instance void Method() {}
}

All methods declared in an interface are marked as virtual abstract, and all methods that implement interface methods in classes are marked as virtual final, so the CLR knows it can't just call them directly - it has to do vtable lookups at runtime to call the right implementation. The interface implementations are still virtual, but you can't override them as they're final.

As an example, the following C# definition:

public interface IInterface {
    void Method();
}

public class Class : IInterface {
    public void Method() {}
}

compiles to the following IL:

.class public interface abstract IInterface {
    .method public abstract virtual instance void Method() {}
}

.class public Class extends [mscorlib]System.Object implements IInterface {
    .method public specialname rtspecialname instance void .ctor() {}
    .method public virtual final instance void Method() {}
}
花期渐远 2024-10-21 18:27:52

我相信当你实现一个接口时,你从接口继承的方法会自动标记为虚拟的,所以逻辑没问题,你不需要测试。

I believe when you implement an interface, the methods you inherit from the interface are automatically marked as virtual, so the logic's fine, and you don't need the test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文