Mono Cecil获取委托方法参数



下面是一个非常简单的程序集。我正在尝试使用单声道。Cecil反射它,以找到传递给所有调用CallApiAsync的参数。当我我似乎无法获得参数 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())
                    }
                }
            }

会有我的线索告诉你如何做你想做的,但我还没有做到。问题是,async/await是语法糖,所以您的MakeSomeRequestToApiCallApi方法都被编译器扩展为以下代码(有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和委托使它成为一项工作。希望我能帮到你。

注:代码已被ILSpy工具反编译,并关闭了"反编译异步方法"选项

相关内容

  • 没有找到相关文章

最新更新