Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.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# 对象上的Reflection.Emit-IL-call方法_C#_.net_Reflection_Compiler Construction_Emit - Fatal编程技术网

C# 对象上的Reflection.Emit-IL-call方法

C# 对象上的Reflection.Emit-IL-call方法,c#,.net,reflection,compiler-construction,emit,C#,.net,Reflection,Compiler Construction,Emit,我正在研究在运行时创建一个动态方法来复制一个对象。让我们假设: class Source { public List<int> L1 {get;set;} } class Dest { public List<int> L1 {get;set;} } 这一切都很好。。。现在是棘手的部分。让我们将Dest更改为: class Dest { private List<int> _l1 = new List<int>(); p

我正在研究在运行时创建一个动态方法来复制一个对象。让我们假设:

class Source
{
   public List<int> L1 {get;set;}
}

class Dest
{
   public List<int> L1 {get;set;}
}
这一切都很好。。。现在是棘手的部分。让我们将Dest更改为:

class Dest
{
   private List<int> _l1 = new List<int>();
   public List<int> L1 {get { return _l1; } }
}

我需要如何在TODO块中设置IL?我尝试执行dup/loadArg0/call miGetter/call miClear,但这给了我一个无效的程序。

下面是一个工作示例,解释了在每个步骤中计算堆栈发生的情况:

DynamicMethod method =
    new DynamicMethod("Test", typeof(Dest), new Type[] { typeof(Source) });

var generator = method.GetILGenerator();

var constructor = typeof(Dest).GetConstructor(Type.EmptyTypes);

var miGetter = typeof(Source).GetProperty("L1").GetMethod;

var miDestGetter = typeof(Dest).GetProperty("L1").GetMethod;

var addRange = typeof(List<int>).GetMethod("AddRange");

var clear = typeof(List<int>).GetMethod("Clear");

generator.Emit(OpCodes.Newobj, constructor);//Stack: DestObject

generator.Emit(OpCodes.Dup);//Stack: DestObject,DestObject

generator.Emit(OpCodes.Call, miDestGetter);//Stack: DestObject,DestObject.L1

generator.Emit(OpCodes.Dup);//Stack: DestObject,DestObject.L1,DestObject.L1

generator.Emit(OpCodes.Call, clear);//Stack: DestObject,DestObject.L1

generator.Emit(OpCodes.Ldarg_0);//Stack: DestObject,DestObject.L1,SourceObject

generator.Emit(OpCodes.Call, miGetter);//Stack: DestObject,DestObject.L1,SourceObject.L1

generator.Emit(OpCodes.Call, addRange);//Stack: DestObject

generator.Emit(OpCodes.Ret);

var function = (Func<Source, Dest>)method.CreateDelegate(typeof(Func<Source, Dest>));

Source source = new Source
{
    L1 = new List<int>() { 1, 2, 3 }
};

var result = function(source);
DynamicMethod方法=
新的动态方法(“测试”,typeof(Dest),新类型[]{typeof(Source)});
var生成器=方法.GetILGenerator();
var constructor=typeof(Dest).GetConstructor(Type.EmptyTypes);
var miGetter=typeof(Source.GetProperty(“L1”).GetMethod;
var miDestGetter=typeof(Dest).GetProperty(“L1”).GetMethod;
var addRange=typeof(List).GetMethod(“addRange”);
var clear=typeof(List).GetMethod(“clear”);
生成器.Emit(操作码.Newobj,构造函数)//堆栈:DestObject
生成器.Emit(操作码.Dup)//堆栈:DestObject,DestObject
生成器.Emit(操作码.Call,MIDESTGETER)//堆栈:DestObject,DestObject.L1
生成器.Emit(操作码.Dup)//堆栈:DestObject,DestObject.L1,DestObject.L1
生成器.Emit(操作码.Call,清除)//堆栈:DestObject,DestObject.L1
生成器.Emit(操作码.Ldarg_0)//堆栈:DestObject,DestObject.L1,SourceObject
生成器.Emit(操作码.Call,miGetter)//堆栈:DestObject、DestObject.L1、SourceObject.L1
生成器.Emit(操作码.Call,addRange)//堆栈:DestObject
生成器.Emit(操作码.Ret);
var function=(Func)method.CreateDelegate(typeof(Func));
来源=新来源
{
L1=新列表(){1,2,3}
};
var结果=函数(源);

为什么要调用
清除
?您不是正在创建一个新的
Dest
?在构建时它将是空的。请参阅下面的Dest down的第二个版本。L1现在是只读集合,所以不能调用setter(可以,但不应该),这不是我的问题。创建新的
Dest
时,
L1
列表为空。您需要调用
AddRange
,但不必先调用
Clear
。我再次建议您使用高级语言编写代码,并使用反编译器获取操作的有效IL指令。你在这种方法上遇到过什么问题吗?@YacoubMassad,是的,我知道当你重新开始时,列表将是空的。。。除非构造器向其中添加内容。。。角落的情况下,只是为了安全:)。
        generator.Emit(OpCodes.Newobj, constructor);

        // this block is repeated 5 times for various properties

        generator.Emit(OpCodes.Dup);
        generator.Emit(OpCodes.Ldarg_0);
        generator.Emit(OpCodes.Callvirt, miGetter);
        generator.Emit(OpCodes.Callvirt, miSetter);

        // List property will be copied here
        // miGetter = Dest.L1.Get
        // TODO
        // end list property

        generator.Emit(OpCodes.Ret);
DynamicMethod method =
    new DynamicMethod("Test", typeof(Dest), new Type[] { typeof(Source) });

var generator = method.GetILGenerator();

var constructor = typeof(Dest).GetConstructor(Type.EmptyTypes);

var miGetter = typeof(Source).GetProperty("L1").GetMethod;

var miDestGetter = typeof(Dest).GetProperty("L1").GetMethod;

var addRange = typeof(List<int>).GetMethod("AddRange");

var clear = typeof(List<int>).GetMethod("Clear");

generator.Emit(OpCodes.Newobj, constructor);//Stack: DestObject

generator.Emit(OpCodes.Dup);//Stack: DestObject,DestObject

generator.Emit(OpCodes.Call, miDestGetter);//Stack: DestObject,DestObject.L1

generator.Emit(OpCodes.Dup);//Stack: DestObject,DestObject.L1,DestObject.L1

generator.Emit(OpCodes.Call, clear);//Stack: DestObject,DestObject.L1

generator.Emit(OpCodes.Ldarg_0);//Stack: DestObject,DestObject.L1,SourceObject

generator.Emit(OpCodes.Call, miGetter);//Stack: DestObject,DestObject.L1,SourceObject.L1

generator.Emit(OpCodes.Call, addRange);//Stack: DestObject

generator.Emit(OpCodes.Ret);

var function = (Func<Source, Dest>)method.CreateDelegate(typeof(Func<Source, Dest>));

Source source = new Source
{
    L1 = new List<int>() { 1, 2, 3 }
};

var result = function(source);