Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么';查找引用特定程序集的所有其他程序集的最有效方法是什么?_C#_Unity3d_Reflection_Assemblies - Fatal编程技术网

C# 什么';查找引用特定程序集的所有其他程序集的最有效方法是什么?

C# 什么';查找引用特定程序集的所有其他程序集的最有效方法是什么?,c#,unity3d,reflection,assemblies,C#,Unity3d,Reflection,Assemblies,我经常发现自己出于各种原因想要迭代当前环境中的所有类型,比如查找从特定类继承的所有类型,或者查找具有特定属性的所有类型 我可以使用System.AppDomain.CurrentDomain.GetAssemblies()获取所有程序集,然后对每个程序集执行Assembly.GetTypes(),并遍历所有类型。但这是毫无必要的低效;在一个包含单个脚本的项目中的Unity编辑器中,此方法需要处理8590种类型,其中大多数类型都不可能满足我搜索的条件。例如,mscorlib.dll或UnityEn

我经常发现自己出于各种原因想要迭代当前环境中的所有类型,比如查找从特定类继承的所有类型,或者查找具有特定属性的所有类型

我可以使用
System.AppDomain.CurrentDomain.GetAssemblies()
获取所有程序集,然后对每个程序集执行
Assembly.GetTypes()
,并遍历所有类型。但这是毫无必要的低效;在一个包含单个脚本的项目中的Unity编辑器中,此方法需要处理8590种类型,其中大多数类型都不可能满足我搜索的条件。例如,mscorlib.dll或UnityEngine.dll中的任何内容都不会具有我的自定义属性或从我的某个类继承,因此我应该跳过这些程序集

现在,我试图找到引用任何给定程序集的所有程序集,但是我很难找到一个有效的算法来找到它们,因为我只能得到目标引用的程序集数组,而不能得到引用目标的程序集数组


还请注意,如果程序集A引用B,B引用C,则在搜索引用C的所有内容时,我需要同时获取A和B(如果B中的某个内容继承自我要查找的类,而A中的某个内容继承自该类,而A中的某个内容没有直接引用C).

依赖性Walker将为您带来神奇的效果。

我从未使用过Unity 2.0,所以我为.NET framework 2.0编写了此代码,希望它能起作用

首先,您可能希望创建部件的树表示形式:

class DependencyTree
{
    public string AssemblyName;
    public IDictionary<string,DependencyTree> ReferencedAssemblies;
}
类依赖树
{
公共字符串名称;
公共索引引用程序集;
}
现在让我们创建一个类来遍历并生成树

class DependencyWalker
{
    Dictionary<string, DependencyTree> _alreadyProcessed = new Dictionary<string, DependencyTree>();

    public DependencyTree GetDependencyTree(Assembly assembly)
    {
        // Avoid procesing twice same assembly.
        if (_alreadyProcessed.ContainsKey(assembly.FullName)) 
            return _alreadyProcessed[assembly.FullName]; 

        var item = new DependencyTree();
        item.AssemblyName = assembly.FullName;
        item.ReferencedAssemblies = new Dictionary<string, DependencyTree>();

        _alreadyProcessed.Add(item.AssemblyName, item);

        foreach (AssemblyName assemblyName in assembly.GetReferencedAssemblies())
        {
            item.ReferencedAssemblies.Add(assemblyName.FullName, GetDependencyTree(Assembly.Load(assemblyName)));
        }

        return item;
    }

    // To print the tree to the console:
    public void PrintTree(DependencyTree tree)
    {
        PrintTree(tree, 0, new Dictionary<string, bool>()); // Using Dictionary because HashSet is not available on .NET 2.0
    }

    private void PrintTree(DependencyTree tree, int indentationLevel, IDictionary<string,bool> alreadyPrinted)
    {
        Console.WriteLine(new string(' ', indentationLevel) + tree.AssemblyName);

        if (alreadyPrinted.ContainsKey(tree.AssemblyName))
            return;

        alreadyPrinted[tree.AssemblyName] = true;

        foreach (DependencyTree a in tree.ReferencedAssemblies.Values)
            PrintTree(a, indentationLevel + 3, alreadyPrinted);

    }
}
class DependencyWalker
{
字典_alreadyProcessed=新字典();
公共DependencyTree GetDependencyTree(程序集)
{
//避免对同一组件进行两次加工。
if(_alreadyProcessed.ContainsKey(assembly.FullName))
return _alreadyProcessed[assembly.FullName];
var item=新的DependencyTree();
item.AssemblyName=assembly.FullName;
item.ReferencedAssemblys=新字典();
_添加(item.AssemblyName,item);
foreach(assembly.GetReferencedAssemblys()中的AssemblyName AssemblyName)
{
item.ReferencedAssemblys.Add(assemblyName.FullName,GetDependencyTree(Assembly.Load(assemblyName)));
}
退货项目;
}
//要将树打印到控制台,请执行以下操作:
公共void打印树(DependencyTree树)
{
PrintTree(tree,0,new Dictionary());//正在使用Dictionary,因为.NET 2.0上没有HashSet
}
私有void打印树(DependencyTree树,int-indicationLevel,IDictionary-alreadyPrinted)
{
Console.WriteLine(新字符串(“”,indicationLevel)+tree.AssemblyName);
if(alreadyPrinted.ContainsKey(tree.AssemblyName))
返回;
alreadyPrinted[tree.AssemblyName]=true;
foreach(tree.ReferencedAssemblys.Values中的DependencyTree a)
打印树(a,缩进级别+3,已打印);
}
}
现在,您可以轻松使用该类:

class Program
{
    static void Main(string[] args)
    {
        new System.Xml.XmlDocument().LoadXml("<xml/>"); // Do whatever to ensure System.Xml assembly is referenced.

        var startingAssembly = typeof(Program).Assembly;
        var walker = new DependencyWalker();
        var tree = walker.GetDependencyTree(startingAssembly);
        walker.PrintTree(tree);
    }
}
类程序
{
静态void Main(字符串[]参数)
{
new System.Xml.XmlDocument().LoadXml(“”;//尽一切努力确保引用System.Xml程序集。
var startingAssembly=typeof(Program).Assembly;
var walker=新的DependencyWalker();
var-tree=walker.GetDependencyTree(startingAssembly);
印刷树;
}
}
哪些输出

ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a System.Data.SqlXml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ConsoleApplication1,版本=1.0.0.0,区域性=中立,PublicKeyToken=null mscorlib,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 Xml,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089 mscorlib,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 系统,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 mscorlib,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 System.Configuration,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b03f5f7f11d50a3a mscorlib,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 系统,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 Xml,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089 System.Security,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b03f5f7f11d50a3a mscorlib,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 系统,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 Xml,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089 Xml,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089 System.Configuration,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b03f5f7f11d50a3a System.Data.SqlXml,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 系统,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 mscorlib,版本=2.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089 Xml,版本=2.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089
请注意,生成器输出一个具有循环的树,因此在递归函数上遍历它将是一个无限循环。在PrintTree中,我使用
alreadyPrinted
列表避免无限循环。(我只打印一次子引用列表,以避免循环。)YMMV,因此请根据您的需要更改它。

您的目标是哪个.NET framework或NET标准库?对于第一种方法,如果您筛选要迭代的程序集,您可以加快速度