Что эквивалентно коду ниже в Reflection.Emit IL - PullRequest
0 голосов
/ 10 июля 2011
void DoSomething(Data data){
    var myDataRequest = new DataRequest();
    myDataRequest.ID = data.ID
}

У меня есть следующее

 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;
        }

Iздесь приведен следующий код: http://pservicebusext.codeplex.com/SourceControl/changeset/view/4f8a4f1190ae#PServiceBus.RemoteProxy%2fPServiceBus.RemoteProxy%2fESBProxy.cs

Существует метод с именем CreateProxy (), который предполагает генерацию приведенного выше кода.Но часть зацикливается и генерирует get и set для метода не работает должным образом.Он никогда не устанавливает значения объекта запроса, он всегда остается нулевым

1 Ответ

2 голосов
/ 10 июля 2011

Легко, скомпилируйте свой метод и используйте некоторый декомпилятор (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);
    }
}

Может быть, вы забыли объявить локальные переменные выиспользуя

...