下面是一个非常简单的程序集。我正在尝试使用单声道。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是语法糖,所以您的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和委托使它成为一项工作。希望我能帮到你。
注:代码已被ILSpy工具反编译,并关闭了"反编译异步方法"选项