c# – 如何使用Cecil查找传递给泛型方法的类型?
发布时间:2020-12-15 05:38:43 所属栏目:百科 来源:网络整理
导读:我正在尝试使用Cecil来查找使用常规测试接口的泛型方法调用的实例.我无法从MethodReference中识别泛型类型. 我已经设置了一个基本测试: private interface IAnimal{}private class Duck : IAnimal{}private class Farm{ private readonly ICollectionstring
我正在尝试使用Cecil来查找使用常规测试接口的泛型方法调用的实例.我无法从MethodReference中识别泛型类型.
我已经设置了一个基本测试: private interface IAnimal { } private class Duck : IAnimal { } private class Farm { private readonly ICollection<string> _animals = new List<string>(); public void Add<T>() { _animals.Add(typeof(T).Name); } public override string ToString() { return string.Join(",",_animals); } } static Farm FarmFactory() { var farm = new Farm(); farm.Add<Duck>(); farm.Add<Duck>(); farm.Add<IAnimal>(); // whoops farm.Add<Duck>(); return farm; } private static void Main(string[] args) { var farm = FarmFactory(); Console.WriteLine("Farm:"); Console.WriteLine(farm); // Use Cecil to find the call to farm.Add<IAnimal>(): Console.WriteLine("Errors:"); FindErrors(); Console.Read(); } 所以我想找到对farm.Add< IAnimal>()的调用,它不会产生编译时错误甚至是运行时错误,直到该场可以想象通过反射创建该类型的实例.我的实际用例是DI容器的常规测试. 塞西尔在FindErrors()方法中加入了它: private static void FindErrors() { var methods = AssemblyDefinition.ReadAssembly(typeof (Farm).Assembly.Location) .Modules .SelectMany(module => module.Types) .SelectMany(type => type.Methods) .Where(method => method.HasBody) .ToArray() ; var callsToFarmDotAdd = methods .Select(method => new { Name = method.Name,MethodReferences = GetCallsToFarmDotAdd(method) }) .Where(x => x.MethodReferences.Any()) .ToArray() ; var testCases = callsToFarmDotAdd .SelectMany(x => x.MethodReferences) ; var callsInError = testCases .Where(test => !test.GenericParameters[0].Resolve().IsClass) ; foreach (var error in callsInError) { Console.WriteLine(error.FullName); } } private static IEnumerable<MethodReference> GetCallsToFarmDotAdd(MethodDefinition method) { return method.Body.Instructions .Where(instruction => instruction.OpCode == OpCodes.Callvirt) .Select(instruction => (MethodReference) instruction.Operand) .Where(methodReference => methodReference.FullName.Contains("Farm::Add")) ; } callsInError部分是我无法识别调用Farm :: Add时使用的泛型类型的地方.具体来说,MethodReference的GenericParameters属性为空,因此GenericParameters [0]给出了ArgumentOutOfRangeException.我已经探索了MethodReference,我肯定得到了对Farm :: Add的调用,但我看不到任何与正在使用的泛型类型有关的地方,除了FullName属性,这是没用的. 如何让Cecil识别呼叫中使用的泛型类型? 解决方法
如果我将MethodReference转换为GenericInstanceMethod,则GenericArguments参数执行我需要的操作:
var callsInError = testCases .Where(test => !((GenericInstanceMethod)test).GenericArguments[0].Resolve().IsClass) ; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |