如何解决使用反射检测在 C# 方法中调用了哪个异步重载
使用反射,我需要确定特定异步方法正在调用哪些重载。在这种情况下,我需要检查 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 举报,一经查实,本站将立刻删除。