2011-07-10 48 views
0
void DoSomething(Data data){ 
    var myDataRequest = new DataRequest(); 
    myDataRequest.ID = data.ID 
} 

我有以下什麼是Reflection.Emit的IL代碼如下的equivilent

methodIL.Emit(OpCodes.Ldloc_1); 
methodIL.Emit(OpCodes.Ldarg_0); 
methodIL.Emit(OpCodes.Callvirt, getMethodForData); 
methodIL.Emit(OpCodes.Callvirt, setMethodForDataRequest); 
methodIL.Emit(OpCodes.Nop); 

但它似乎沒有工作

代碼,我真的要產生:

static Response TestRequestResponse(RequestData requestData) { 
      var wrapper = new WrapperResponse<Response>(); 
      var request = new Request() { }; 
      request.RequestID = requestData.RequestID; 
      request.Value = requestData.Value; 
      request.ID = requestData.ID; 
      request.OnReply(wrapper.Handle); 
      request.WaitForResponse(true); 
      request.TimeOut(TimeSpan.FromSeconds(30)); 
      request.Send(); 
      return wrapper.Response; 
     } 

我在這裏有以下代碼:http://pservicebusext.codeplex.com/SourceControl/changeset/view/4f8a4f1190ae#PServiceBus.RemoteProxy%2fPServiceBus.RemoteProxy%2fESBProxy.cs

有一個名爲CreateProxy()的方法,它假設生成上面的代碼。但是零件循環並生成方法的get和set不能正常工作。它從來沒有請求對象的值,它總是保留爲空

我解決了這個問題,我使用OpCodes.Ldarg_0到OpCodes.Ldarg_1

改變
methodIL.Emit(OpCodes.Ldloc_1); 
methodIL.Emit(OpCodes.Ldarg_1); 
methodIL.Emit(OpCodes.Callvirt, getMethodForData); 
methodIL.Emit(OpCodes.Callvirt, setMethodForDataRequest); 
methodIL.Emit(OpCodes.Nop); 
+0

如果您使用.net 4,那麼您可以編譯基於表達式樹的方法,這很容易創建。 –

+0

我使用reflection.emit的原因是因爲我正在根據接口方法生成一個類。表達式樹不適合這種情況。 – rpgmaker

+0

我認爲你可以將表達式樹編譯到現有的方法構建器中。這可能會讓你實現一個接口。 – CodesInChaos

回答

2

簡單,編譯你的方法,並使用一些反編譯器(Reflector甚至LINQPad)讀取IL。我得到了以下的IL:

IL_0000: newobj  DataRequest..ctor 
IL_0005: stloc.0  
IL_0006: ldloc.0  
IL_0007: ldarg.1  
IL_0008: callvirt Data.get_ID 
IL_000D: callvirt DataRequest.set_ID 
IL_0012: ret 

編輯:下面的代碼對我的作品:

public class DataRequest 
{ 
    public DataRequest() 
    {} 

    private int m_id; 
    public int ID 
    { 
     get { return m_id; } 
     set { m_id = value; } 
    } 
} 

public class Data 
{ 
    private int m_id; 
    public int ID 
    { 
     get { return m_id; } 
     set { m_id = value; } 
    } 
} 

class Program 
{ 
    static void Main() 
    { 
     var method = new DynamicMethod("DoSomething", typeof(void), new[] { typeof(Data) }); 
     var methodIL = method.GetILGenerator(); 
     var constructor = typeof(DataRequest).GetConstructor(new Type[0]); 
     var getMethodForData = typeof(Data).GetProperty("ID").GetGetMethod(); 
     var setMethodForDataRequest = typeof(DataRequest).GetProperty("ID").GetSetMethod(); 
     methodIL.Emit(OpCodes.Newobj, constructor); 
     // storing and loading the same object to the some local is useless 
     //var dataReuqest = methodIL.DeclareLocal(typeof(DataRequest)); 
     //methodIL.Emit(OpCodes.Stloc, dataReuqest.LocalIndex); 
     //methodIL.Emit(OpCodes.Ldloc, dataReuqest.LocalIndex); 
     methodIL.Emit(OpCodes.Ldarg_0); 
     methodIL.Emit(OpCodes.Callvirt, getMethodForData); 
     methodIL.Emit(OpCodes.Callvirt, setMethodForDataRequest); 
     methodIL.Emit(OpCodes.Ret); 
     var f = (Action<Data>)method.CreateDelegate(typeof(Action<Data>)); 
     var data = new Data { ID = 42 }; 
     f(data); 
    } 
} 

也許你忘了申報你使用局部變量?

+0

這與我的代碼相同,上面也是。我只顯示了reflection.emit代碼獲取和設置。我已經有了newobj,但它仍然不起作用 – rpgmaker

+0

它不起作用?它有什麼作用?你如何使用emited代碼? – svick

+0

查看我對原文所做的更改,我所指的是 – rpgmaker