首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在虚拟方法上使用OpCodes.Call安全吗?

在虚拟方法上使用OpCodes.Call安全吗?
EN

Stack Overflow用户
提问于 2015-06-22 04:39:12
回答 1查看 240关注 0票数 2

我在玩为属性生成动态代理。

生成的代理来自我们希望代理的类型。当代理需要访问它派生的类型上的(虚拟)属性时,不能使用OpCodes.Callvirt --它会导致无限递归。因此,我们需要调用OpCodes.Call。我注意到如果我有:

代码语言:javascript
复制
public class MyParent 
{
    protected string _name;
    protected string _color;

    public virtual string Name
    {
        get { return _name; }
        set { _name = value; }
    }
    public virtual string Color
    {
        get { return _color; }
        set { _color = value; }
    }
}

public class MyChild : MyParent
{
    public override string Name {
        get { return "42"; }
        set { _name = value; } 
    }
}

当我在从MyChild派生的代理对象上发出MyChild以调用get_Color时,它将被正确地调用,尽管技术上该方法不是在MyChild上实现的。

我打算编写一些代码,将类型层次结构遍历到MyParent,在那里可以找到get_Color实现,并将该类型方法用于OpCodes.Call,但这似乎没有必要:

代码语言:javascript
复制
var thisTypeMethod = property.GetGetMethod();
// I know that the next line technically is not correct because of non-virtual methods 
// and also *new* overrides. Assume I'm doing it correctly, not by property.Name 
// but by repeatedly calling MethodInfo.GetBaseDefinition()
var declaringTypeMethod = property.DeclaringType.GetProperty(property.Name).GetGetMethod();

然后

代码语言:javascript
复制
var proxyMethod = new DynamicMethod(thisTypeMethod.Name,thisTypeMethod.ReturnType, new Type[]{type},type,true);
var il = proxyMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Tailcall);
il.Emit(OpCodes.Call, thisTypeMethod);
il.Emit(OpCodes.Ret);

不使用declaringTypeMethod和使用thisTypeMethod安全吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-22 05:14:24

您通常不希望声明类型中的实现。

想必您希望做与base关键字在C#编译器中所做的相同的事情。C#编译器实际上查找最派生的父实现并直接调用它,但是您所做的也是完全合法的。

如果基类位于另一个程序集中,则它们具有不同的行为,并且在代码生成运行后重新编译该程序集,添加新的重写。有关更多细节,请参阅Eric ( C#编译器主要开发人员之一)的这篇博客文章,其中讨论了这个确切的场景:

  • 把基地放在中间

这个问题说明了针对当前方法的OpCodes.Call与具有实际实现的派生最多的父级之间的行为差异:

重申一下,您不希望在DeclaringType中使用该实现,这通常不是上述两种合理选择中的一种。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30972209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档