问题描述
使用反射,我需要确定特定异步方法正在调用哪些重载。在这种情况下,我需要检查 DoSomething()
方法以确定它正在调用哪个方法调用 MyMethod()
。
首先,考虑以下用于同步版本的 C# 控制台应用程序:
using System;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
namespace CecilReflection
{
public class Program
{
public static void Main(string[] args)
{
var assemblyDeFinition = AssemblyDeFinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
var toInspect = assemblyDeFinition.MainModule
.GetTypes()
.SelectMany(type => type.Methods
.Where(method => method.HasBody)
.Select(method => new
{
Type = type,Method = method
}))
.Where(x => x.Method.Name == "DoSomething");
foreach (var entry in toInspect)
{
Console.WriteLine($"\tType = {entry.Type.Name}\n\t\tMethod = {entry.Method.Name}");
foreach (var instruction in entry.Method.Body.Instructions)
Console.WriteLine($"{instruction.OpCode} \"{instruction.Operand}\"");
}
Console.ReadKey();
}
public static void DoSomething()
{
var myClass = new MyClass();
myClass.MyMethod();
myClass.MyMethod(5);
}
public class MyClass
{
public void MyMethod()
{
}
public void MyMethod(int arg)
{
}
}
}
}
运行它会产生以下输出:
Type = Program
Method = DoSomething
nop ""
newobj "System.Void CecilReflection.Program/MyClass::.ctor()"
stloc.0 ""
ldloc.0 ""
callvirt "System.Void CecilReflection.Program/MyClass::MyMethod()"
nop ""
ldloc.0 ""
ldc.i4.5 ""
callvirt "System.Void CecilReflection.Program/MyClass::MyMethod(system.int32)"
nop ""
ret ""
通过查看 callvirt
条目,我能够检测到使用上述代码调用了 MyMethod()
的两个重载。
这是异步版本:
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Mono.Cecil;
namespace CecilReflection
{
public class Program
{
public static void Main(string[] args)
{
var assemblyDeFinition = AssemblyDeFinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
var toInspect = assemblyDeFinition.MainModule
.GetTypes()
.SelectMany(type => type.Methods
.Where(method => method.HasBody)
.Select(method => new
{
Type = type,Method = method
}))
.Where(x => x.Method.Name == "DoSomething");
foreach (var entry in toInspect)
{
Console.WriteLine($"\tType = {entry.Type.Name}\n\t\tMethod = {entry.Method.Name}");
foreach (var instruction in entry.Method.Body.Instructions)
Console.WriteLine($"{instruction.OpCode} \"{instruction.Operand}\"");
}
Console.ReadKey();
}
public static async Task DoSomething()
{
var myClass = new MyClass();
await myClass.MyMethodAsync();
await myClass.MyMethodAsync(5);
}
public class MyClass
{
public async Task MyMethodAsync()
{
}
public async Task MyMethodAsync(int arg)
{
}
}
}
}
这会产生以下输出:
Type = Program
Method = DoSomething
newobj "System.Void CecilReflection.Program/<DoSomething>d__1::.ctor()"
stloc.0 ""
ldloc.0 ""
call "System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Create()"
stfld "System.Runtime.CompilerServices.AsyncTaskMethodBuilder CecilReflection.Program/<DoSomething>d__1::<>t__builder"
ldloc.0 ""
ldc.i4.m1 ""
stfld "system.int32 CecilReflection.Program/<DoSomething>d__1::<>1__state"
ldloc.0 ""
ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder CecilReflection.Program/<DoSomething>d__1::<>t__builder"
ldloca.s "V_0"
call "System.Void System.Runtime.CompilerServices.AsyncTaskMethodBuilder::Start<CecilReflection.Program/<DoSomething>d__1>(!!0&)"
ldloc.0 ""
ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder CecilReflection.Program/<DoSomething>d__1::<>t__builder"
call "System.Threading.Tasks.Task System.Runtime.CompilerServices.AsyncTaskMethodBuilder::get_Task()"
ret ""
对于异步版本,我无法确定调用了 MyMethodAsync()
的哪些重载(如果有)。
有什么方法可以确定调用了 MyMethodAsync()
的哪些重载?我不要求使用 Mono.Cecil,但使用 System.Reflection
来完成此操作的运气更差。如果完全不同的方法可行,那很好。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)