模块类的resolvemethod 在重写的方法上出现混乱

发布于 2024-11-01 14:44:13 字数 440 浏览 0 评论 0原文

我有一个派生类,其方法覆盖基类的方法,(像这样) 但是 module.ResolveMethod(token, typeArguments, methodArguments) 给了我一个 MethodBase ,其 declaringType 是基本类型,而不是应有的派生类型。

这是 module.ResolveMethod 中的错误吗?

代码发布起来相当复杂,但我使用 Jb Evain 的 MethodBaseRocks

I have a derived class with a method that overrides the base class's method, (like this) but module.ResolveMethod(token, typeArguments, methodArguments) gives me a MethodBase with a declaringType of the base type, not the derived type like it should be.

Is this a bug in module.ResolveMethod?

The code is fairly complex to post, but I am using Jb Evain's MethodBaseRocks

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

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

发布评论

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

评论(1

痴骨ら 2024-11-08 14:44:13

不,您正在使用反射/IL 检查。这是静态代码分析。您没有对类型的特定运行时实例执行任何操作。

多态性在运行时“评估”:运行时决定(基于对象的实际类型)调用虚拟方法的哪个版本(基类或派生类)。

您的代码似乎在特定类型上查找方法,根据定义,该方法将返回该类型的方法,因为您正在按原样检查元数据(基类声明基类方法,派生类声明派生方法,没什么花哨的;这只是事实)。

我认为(IIRC)Mono.Cecil(来自 JbEvain)在 MethodDefinition 上公开了 Overloads 集合。我想您可能必须调用 MethodReference.Resolve() 才能获取 MethodDefinition。


如果需要更多背景知识

没有安全的反射方法可以根据在 CIL 中执行 callvirt 时应用的运行时规则来调用虚拟方法。即即使你这样做:

class BaseClass
{ public virtual void SomeMethod() {} }

class Derived :BaseClass {}

class MainClass
{
    public static void Main (string[] args)
    {
        Expression<Action<Derived>> expr = (instance) => instance.SomeMethod();
        var method = (expr.Body as MethodCallExpression).Method;
        Console.WriteLine(method.DeclaringType);
    }
}

它也会打印 NamespaceName.BaseClass 因为它是声明虚拟的类。

No, you are using reflection/IL inspection. This is static code analysis. You are not doing anything on a specific runtime instance of a type.

Polymorphism is 'evaluated' at runtime: the runtime decides (based on the actual type of the object) which version of the virtual method to call (base or derived).

Your code seems to look a method up on a specific type, which will by definition return the method from that type, because you are inspecting the metadata as it is (the base declares the base method, the derived declares the derived method, nothing fancy; it's just the facts).

I think (IIRC) Mono.Cecil (from JbEvain) exposes an Overloads collection on the MethodDefinition. I suppose you may have to call MethodReference.Resolve() in order to get the MethodDefinition.


more background if desired:

There is no safe reflection way to invoke a virtual method according to runtime rules that apply when doing a callvirt in CIL. I.e. even if you do:

class BaseClass
{ public virtual void SomeMethod() {} }

class Derived :BaseClass {}

class MainClass
{
    public static void Main (string[] args)
    {
        Expression<Action<Derived>> expr = (instance) => instance.SomeMethod();
        var method = (expr.Body as MethodCallExpression).Method;
        Console.WriteLine(method.DeclaringType);
    }
}

it will print NamespaceName.BaseClass because it is the class that declares the virtual.

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