Mono Cecil获得委托方法参数

时间:2015-07-30 22:03:03

标签: reflection delegates mono.cecil

我下面有一个非常简单的装配。我试图使用Mono.Cecil来反映它,以找到传递给所有CallApiAsync调用的参数。当我 隔离MethodReference用于调用我似乎无法获得参数 x.GetResponse(new SomeRequestType()) ,我只是得到了委托定义 ApiMethodAsync<T, TResult> 。我已经在这上面写了一个空白,任何帮助表示赞赏。

public class ApiWrapper
{
 public delegate Task<TResult> ApiMethodAsync<T, TResult>(T api);

 public virtual async Task<SomeResponseType> MakeSomeRequestToApi() 
 {
    return await CallApiAsync<ISomeApi, SomeResponseType>(x => x.GetResponse(new SomeRequestType()));
 }

 public virtual async Task<TResult> CallApiAsync<T, TResult>(ApiMethodAsync<T, TResult> apiMethod) where TResult : new()
 {
    return await Task.FromResult(new TResult());
 }
}

public interface ISomeApi
{
    Task<SomeResponseType> GetResponse(SomeRequestType request);
}

public class SomeResponseType { }
public class SomeRequestType { }

下面是我用来识别对CallApiAsync

的调用的Mono Cecil代码
var moduleDefinition = ModuleDefinition.ReadModule("SimpleAssembly.dll");

var targetClass = moduleDefinition.Types.Where(t => t.FullName.Contains("ApiWrapper")).Single();

            var nestedMethodInstructions = targetClass.NestedTypes
                                                      .SelectMany(p => p.Methods)
                                                      .Where(m => m.HasBody)
                                                      .SelectMany(t => t.Body.Instructions).ToList();

            foreach (var instr in nestedMethodInstructions)
            {
                if (instr.Operand != null)
                {
                    var methodRef = instr.Operand as MethodReference;

                    if (methodRef != null && methodRef.FullName.Contains("CallApiAsync"))
                    {
                        // Get the full delegate parameter, ie  GetResponse(new SomeRequestType())
                    }
                }
            }

1 个答案:

答案 0 :(得分:0)

我会知道如何做你想做的事,但我还没有设法做到。问题是,async / await是一种语法糖,因此编译器将 MakeSomeRequestToApi CallApi 方法扩展为以下代码(MakeSomeRequestToApi和CallApi看起来相当漂亮大致相同):

[CompilerGenerated]
[StructLayout(LayoutKind.Auto)]
private struct <MakeSomeRequestToApi>d__2 : IAsyncStateMachine
{
        public int <>1__state;

        public AsyncTaskMethodBuilder<SomeResponseType> <>t__builder;

        public ApiWrapper <>4__this;

        private TaskAwaiter<SomeResponseType> <>u__$awaiter3;

        private object <>t__stack;

        void IAsyncStateMachine.MoveNext()
        {
            SomeResponseType result;
            try
            {
                int num = this.<>1__state;
                if (num != -3)
                {
                    TaskAwaiter<SomeResponseType> taskAwaiter;
                    if (num != 0)
                    {
                        ApiWrapper arg_43_0 = this.<>4__this;
                        if (ApiWrapper.CS$<>9__CachedAnonymousMethodDelegate1 == null)
                        {
                            ApiWrapper.CS$<>9__CachedAnonymousMethodDelegate1 = new ApiWrapper.ApiMethodAsync<ISomeApi, SomeResponseType>(ApiWrapper.<MakeSomeRequestToApi>b__0);
                        }
                        taskAwaiter = arg_43_0.CallApiAsync<ISomeApi, SomeResponseType>(ApiWrapper.CS$<>9__CachedAnonymousMethodDelegate1).GetAwaiter();
                        if (!taskAwaiter.IsCompleted)
                        {
                            this.<>1__state = 0;
                            this.<>u__$awaiter3 = taskAwaiter;
                            this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter<SomeResponseType>, ApiWrapper.<MakeSomeRequestToApi>d__2>(ref taskAwaiter, ref this);
                            return;
                        }
                    }
                    else
                    {
                        taskAwaiter = this.<>u__$awaiter3;
                        this.<>u__$awaiter3 = default(TaskAwaiter<SomeResponseType>);
                        this.<>1__state = -1;
                    }
                    SomeResponseType arg_A8_0 = taskAwaiter.GetResult();
                    taskAwaiter = default(TaskAwaiter<SomeResponseType>);
                    result = arg_A8_0;
                }
            }
            catch (Exception exception)
            {
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult(result);
        }

        [DebuggerHidden]
        void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine param0)
        {
            this.<>t__builder.SetStateMachine(param0);
        }
    }

在结构中间有一条线

ApiWrapper.CS$<>9__CachedAnonymousMethodDelegate1 = new ApiWrapper.ApiMethodAsync<ISomeApi, SomeResponseType>(ApiWrapper.<MakeSomeRequestToApi>b__0);

源代码中的内容如下:

CallApiAsync<ISomeApi, SomeResponseType>(x => x.GetResponse(new SomeRequestType()));

在构造函数中传递的参数位于一行的末尾:

[CompilerGenerated]
    private static Task<SomeResponseType> <MakeSomeRequestToApi>b__0(ISomeApi x)
    {
        return x.GetResponse(new SomeRequestType());
    }

所以,总而言之,我确信可以在操作数和指令中查找所有这些内容,但async / await和delegates使它成为一件好事。希望我帮了一下。

P.S。 该代码已被ILSpy工具反编译,其中&#34;反编译异步方法&#34;选项已关闭