如何在任何基于 CLR 的语言程序集中找到给定类型的所有类型依赖性?

发布于 2024-08-17 23:53:44 字数 830 浏览 7 评论 0原文

我试图找到给定类型所依赖的所有类型,包括接口、抽象类、枚举、结构等。我想加载一个程序集,并打印出其中定义的所有类型的列表,并且他们的依赖。

到目前为止,我已经能够使用 Mono.Cecil 找到 CLR 程序集依赖的所有外部类型,例如

using System;
using Mono.Cecil;
using System.IO;

FileInfo f = new FileInfo("SomeAssembly.dll");
AssemblyDefinition assemDef = AssemblyFactory.GetAssembly (f.FullName); 
List<TypeReference> trList = new List<TypeReference>();

foreach(TypeReference tr in assemblyDef.MainModule.TypeReferences){
    trList.Add(tr.FullName);
}

这个列表也可以使用 mono disasembler 获得,例如“monodis SomeAssembly.dll --typeref”,但是这个列表没有似乎包含基元,例如 System.Void、System.Int32 等,

我需要单独处理每个类型,并获取给定类型所依赖的所有类型,即使这些类型是在同一程序集中定义的。 有没有办法使用 Mono.Cecil 或任何其他项目来做到这一点?

我知道可以通过加载程序集,然后迭代每个定义的类型,然后加载该类型的 IL 并扫描它以获取引用来完成,但我确信有更好的方法。理想情况下,它也适用于匿名内部类。

如果在同一个程序集中定义了多个模块,它也应该起作用。

I am trying to find all the types that a given type is dependent on, including interfaces, abstract classes, enums, structs, etc. I want to load up an assembly, and print out a list of all the types defined within it, and their dependencies.

So far I have been able to find all the the external types a CLR assembly depends on using Mono.Cecil, e.g.

using System;
using Mono.Cecil;
using System.IO;

FileInfo f = new FileInfo("SomeAssembly.dll");
AssemblyDefinition assemDef = AssemblyFactory.GetAssembly (f.FullName); 
List<TypeReference> trList = new List<TypeReference>();

foreach(TypeReference tr in assemblyDef.MainModule.TypeReferences){
    trList.Add(tr.FullName);
}

This list can also be obtained using the mono disasembler, eg "monodis SomeAssembly.dll --typeref", but this list doesnt seem to include primitives, eg System.Void, System.Int32, etc

I need to treat each type individually, and get all types that a given type depends on, even if the types are defined in the same assembly.
Is there any way to do this using Mono.Cecil, or any other project?

I know it can be done by loading the assembly, then iterating over each defined type, then loading the IL of the type and scanning it for references, but I am sure that there is a better way. Ideally it will also work with anonymous inner classes.

It should also work if multiple modules are defined in the same assembly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

丶视觉 2024-08-24 23:53:44

阿杰,
我遇到了同样的问题,我需要遍历程序集中的类型,因此我决定使用 Mono.Cecil。我能够遍历每个类以及类中的属性不是另一个类而不是 CLR 类型的方式是通过递归函数。

    private void BuildTree(ModuleDefinition tempModuleDef , TypeDefinition tempTypeDef, TreeNode rootNode = null)
    {
            AssemblyTypeList.Add(tempTypeDef);

            TreeNode tvTop = new TreeNode(tempTypeDef.Name);

            // list all properties
            foreach (PropertyDefinition tempPropertyDef in tempTypeDef.Properties)
            {
                //Check if the Property Type is actually a POCO in the same Assembly
                if (tempModuleDef.Types.Any(q => q.FullName == tempPropertyDef.PropertyType.FullName))
                {
                    TypeDefinition theType = tempModuleDef.Types.Where( q => q.FullName == tempPropertyDef.PropertyType.FullName)
                                                                .FirstOrDefault();
                    //Recursive Call
                    BuildTree(tempModuleDef, theType, tvTop);

                }

                TreeNode tvProperty = new TreeNode(tempPropertyDef.Name);
                tvTop.Nodes.Add(tvProperty);
            }

            if (rootNode == null)
                tvObjects.Nodes.Add(tvTop);
            else
                rootNode.Nodes.Add(tvTop);

    }

该函数由我的主函数调用,其要点是

      public void Main()
      {
        AssemblyDefinition  assemblyDef = AssemblyDefinition.ReadAssembly(dllname);

        //Populate Tree
        foreach (ModuleDefinition tempModuleDef in assemblyDef.Modules)
        {
            foreach (TypeDefinition tempTypeDef in tempModuleDef.Types)
            {
                BuildTree(tempModuleDef ,tempTypeDef, null);
            }
        }

      }

AJ,
I had the same issue where I needed to traverse the Types in an assembly and I settled on using Mono.Cecil. The way I was able to walk through each Class and if a Property in a Class was not another Class instead of a CLR type was through a recursive function.

    private void BuildTree(ModuleDefinition tempModuleDef , TypeDefinition tempTypeDef, TreeNode rootNode = null)
    {
            AssemblyTypeList.Add(tempTypeDef);

            TreeNode tvTop = new TreeNode(tempTypeDef.Name);

            // list all properties
            foreach (PropertyDefinition tempPropertyDef in tempTypeDef.Properties)
            {
                //Check if the Property Type is actually a POCO in the same Assembly
                if (tempModuleDef.Types.Any(q => q.FullName == tempPropertyDef.PropertyType.FullName))
                {
                    TypeDefinition theType = tempModuleDef.Types.Where( q => q.FullName == tempPropertyDef.PropertyType.FullName)
                                                                .FirstOrDefault();
                    //Recursive Call
                    BuildTree(tempModuleDef, theType, tvTop);

                }

                TreeNode tvProperty = new TreeNode(tempPropertyDef.Name);
                tvTop.Nodes.Add(tvProperty);
            }

            if (rootNode == null)
                tvObjects.Nodes.Add(tvTop);
            else
                rootNode.Nodes.Add(tvTop);

    }

This Function is called by my main Function the gist of which is

      public void Main()
      {
        AssemblyDefinition  assemblyDef = AssemblyDefinition.ReadAssembly(dllname);

        //Populate Tree
        foreach (ModuleDefinition tempModuleDef in assemblyDef.Modules)
        {
            foreach (TypeDefinition tempTypeDef in tempModuleDef.Types)
            {
                BuildTree(tempModuleDef ,tempTypeDef, null);
            }
        }

      }
思慕 2024-08-24 23:53:44

看看 NDepend - 它可以做到这一点,而且还可以做更多的事情。

-奥辛

Have a look at NDepend - it does this, and much more.

-Oisin

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文