![](/img/trans.png)
[英]IL Calling a method with params object[] arguments using Reflection.Emit
[英]Reflection.Emit - IL - call method on object
我正在努力在運行時創建一個動態方法來復制一個對象。 讓我們假設:
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);
所有這一切都很好......現在是棘手的部分。 讓我們改變目的地:
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,但這給了我一個無效的程序。
這是一個工作示例,解釋了每個步驟中評估堆棧的情況:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.