首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >谓词成员引用

问谓词成员引用
EN

Stack Overflow用户
提问于 2021-05-16 04:23:26
回答 1查看 51关注 0票数 1

编译器将LINQ函数谓词转换为名称为"Predicate`1“的FieldInfo。我想分析这些FieldInfo,看看有哪些成员被引用。例如,下面的谓词使用用户定义的方法"ArchName":

代码语言:javascript
复制
list.FindAll(m => !m.ArchName().Contains("<>c"))

我不知道FieldInfo有任何相关的MethodInfo成员。可以做些什么呢?

提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2021-05-16 22:46:34

这与LINQ无关。它是纯粹的C#λ表达式+列表。

在本例中为Predicate 1is not a *field name*, but instead, a type, more preciselySystem.Predicate`。

在我看来,您希望分析方法体以查找对此类型的引用。即使这可能是通过反射来实现的,您也可以使用Mono.Cecil;在这种情况下,您可以使用如下内容(请注意,这段代码并不是以任何方式都不完整...您需要考虑错误、静态字段等):

代码语言:javascript
复制
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;

class Bar
{
    void Foo(List<int> items)
    {
        // A non sense expression :)
        var r = items.FindAll(i => i % 2 == 0 || i.ToString() == "A");
    }

    static void Main()
    {
        var a = AssemblyDefinition.ReadAssembly(typeof(Bar).Assembly.Location);

        var allMethods = a.MainModule.GetTypes().SelectMany(t => t.Methods);

        // find instructions referencing System.Predicate<T>
        var allMethodsReferencingSystemPredicate = allMethods.Where(m => m.Body.Instructions.Any(i => i.OpCode == OpCodes.Newobj && i.Operand.ToString().Contains("System.Predicate`1")));
        foreach(var m in allMethodsReferencingSystemPredicate)
        {
            System.Console.WriteLine($"Analyzing {m}");
            
            var instReferencingSystemPredicate = m.Body.Instructions.Where(i => i.OpCode == OpCodes.Newobj && i.Operand.ToString().Contains("System.Predicate`1"));            
            foreach(var inst in instReferencingSystemPredicate)
            {
                System.Console.WriteLine($"Checking {inst} / {inst.Previous}");
                if (inst.Previous.OpCode != OpCodes.Ldftn)
                {
                    System.Console.WriteLine($"Something went wrong. Expected LdFnt, got {inst.Previous.OpCode} in instruction {inst.Previous}");
                    continue;
                }
                // get the method being referenced.
                var method = ((MethodReference) inst.Previous.Operand).Resolve();
                
                // Analyze the method body looking for calls to `ToString()` (you will replace this with your own checks...)
                foreach(var methodInst in method.Body.Instructions)
                {
                    //System.Console.WriteLine($"Checking: {methodInst}");
                    if ( (methodInst.OpCode == OpCodes.Callvirt || methodInst.OpCode == OpCodes.Call) && methodInst.Operand.ToString().Contains("ToString()"))
                    {
                        System.Console.BackgroundColor = System.ConsoleColor.DarkCyan;
                        System.Console.WriteLine($"{method} (used in {m}) references ToString(): {methodInst}");
                    } 
                }
            }
        }

    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67550907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档