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标准库?对于第一种方法,如果您筛选要迭代的程序集,您可以加快速度