【发布时间】:2016-04-07 21:50:52
【问题描述】:
我正在努力在运行时创建一个动态方法来复制一个对象。让我们假设:
class Source
{
public List<int> L1 {get;set;}
}
class Dest
{
public List<int> L1 {get;set;}
}
现在,这种情况可以正常工作。我得到 Source.L1 并设置 Dest.L1。我使用以下 IL:
generator.Emit(OpCodes.Newobj, constructor);
generator.Emit(OpCodes.Dup);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Callvirt, miGetter);
generator.Emit(OpCodes.Callvirt, miSetter);
generator.Emit(OpCodes.Ret);
所有这一切都很好......现在是棘手的部分。让我们将 Dest 更改为:
class Dest
{
private List<int> _l1 = new List<int>();
public List<int> L1 {get { return _l1; } }
}
现在我想在这种情况下调用 Dest.L1.Clear() 然后调用 Dest.L1.AddRange(...)。
我什至无法让 .Clear 工作。
我还有:
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);
我需要如何在 TODO 块中设置 IL?我尝试执行 dup/loadArg0/call miGetter/call miClear,但这给了我一个无效的程序。
【问题讨论】:
-
为什么要打电话给
Clear?你不是在创建一个新的Dest吗?施工时它将是空的。 -
查看 Dest 的第 2 个版本。 L1 现在是一个只读集合,所以你不能调用 setter(好吧,你可以,但你不应该)
-
这不是我的问题。当您创建新的
Dest时,L1列表为空。您需要拨打AddRange,但您不必先拨打Clear。 -
我再次建议您使用高级语言编写代码并使用反编译器为您的操作获取有效的 IL 指令。您在使用这种方法时遇到任何问题吗?
-
@YacoubMassad,是的,我知道当你新的 Dest 列表将是空的......除非构造函数添加东西......极端情况,只是为了安全:)。
标签: c# .net reflection compiler-construction emit