我下面有一个非常简单的装配。我试图使用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())
}
}
}
答案 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;选项已关闭