Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用操作码安全吗?调用虚拟方法?_C#_.net_Reflection_Reflection.emit - Fatal编程技术网

C# 使用操作码安全吗?调用虚拟方法?

C# 使用操作码安全吗?调用虚拟方法?,c#,.net,reflection,reflection.emit,C#,.net,Reflection,Reflection.emit,我正在玩为属性生成动态代理的游戏 生成的代理是从要代理的类型派生的。 当代理需要访问其派生类型的(虚拟)属性时,OpCodes.Callvirt无法使用-它会导致无限递归。因此,我们需要调用操作码。我注意到,如果我有: public class MyParent { protected string _name; protected string _color; public virtual string Name { get { return

我正在玩为属性生成动态代理的游戏

生成的代理是从要代理的类型派生的。 当代理需要访问其派生类型的(虚拟)属性时,
OpCodes.Callvirt
无法使用-它会导致无限递归。因此,我们需要调用
操作码。我注意到,如果我有:

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
派生的代理对象发出
OpCodes.Call
调用
get\u Color
时,它会被正确调用,即使从技术上讲,此方法没有在
MyChild
上实现

我打算编写一些代码,将类型层次结构向下遍历到
MyParent
,其中可以找到
get\u Color
实现,并将该类型方法用于
操作码。调用
,但这似乎不是必需的:

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();
然后

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安全吗?

您通常不需要声明类型的实现

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

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

此问题说明了
操作码之间的行为差异。针对当前方法调用
,以及具有实际实现的最派生父级:

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