获取程序集而不实例化它们
我试图使用AppDomain.CurrentDomain.GetAssemblies()
在CurrentDomain
获取所有程序集以将其FullName
写入DropDownList
,但是如果我不实例化它们,则在CurrentDomain
GetAssemblies()
返回的数组中看不到它们。
它们都作为参考和解决方案的Reference
文件夹添加。 只有我能从GetAssemblies()
获取它们才是我第一次实例化它们。
如何以简单和更通用的方式克服这个问题,而不是每次添加新的程序集等时实例化它们。
由于公司政策,我必须模糊图像的某些部分:
所有组件都在Reference文件夹中引用:
除了其他人的评论之外,这里发生了一些微妙的事情。
除非实际使用VisualStudio, 否则 VisualStudio实际上不会将.dll引用添加到构建程序集的reflection信息的程序集清单中。
作为示例,创建一个新项目,并引用一个程序集。 我以nunit.framework.dll
为例。
但实际上并没有使用它。 我的代码很简单:
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { } } }
但该项目确实在VisualStudio中引用了NUnit。 现在构建它,并在ildasm.exe
打开程序集,清单的顶部是:
// Metadata version: v4.0.30319 .assembly extern mscorlib { .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } .assembly ConsoleApplication1 { ...etc...
现在,在代码中,只需使用NUnit中的任何内容:
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Assert.IsTrue(true); } } }
再次重建并检查ildasm.exe
的程序集清单:
// Metadata version: v4.0.30319 .assembly extern mscorlib { .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } .assembly extern nunit.framework { .publickeytoken = (96 D0 9A 1E B7 F4 4A 77 ) // ......Jw .ver 2:6:0:12051 } .assembly ConsoleApplication1 { ...etc...
请注意,现在IL中有一个外部。 这也提供reflection,因此它知道要加载的依赖程序集。
过去那些小细节,正如其他人所说,运行时实际上并没有加载一个程序集,直到第一次需要它,因此在你实例化或使用该程序集中的某些东西之前,你的AppDomain没有加载程序集。
当您开始尝试使用Assembly.GetReferencedAssemblies()
方法时,上面的详细信息就会发挥作用。
所以在VisualStudio中,我有一个包含这些引用的项目:
Microsoft.CSharp nunit.framework System System.Core System.Data System.Xml System.Xml.Linq
然后我有C#代码:
using System; using System.Reflection; using NUnit.Framework; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); foreach (var assemblyName in assemblies) { Console.WriteLine(assemblyName.FullName); } Console.ReadKey(); } } }
请注意,我甚至using NUnit.Framework;
声明! 但我实际上并没有在任何地方使用 NUnit,因此它不是引用的程序集。 运行它的输出是:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
这就对了。 如果我将此行添加到我的测试应用中:
Assert.IsTrue(true);
现在实际使用 NUnit,我的控制台输出是:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 nunit.framework, Version=2.6.0.12051, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77
在实例化类型或依赖类型之前,它们不会被加载。 因此,如果您的项目引用了大量的程序集但没有实例化其中的任何类型,那么您的应用程序不会产生从磁盘上加载这些位的性能。
如果要查找项目引用的程序集,则必须使用.NET Reflection浏览程序集。 具体来说,我建议你看一下Assembly.GetReferencedAssemblies()方法。
HTH。
这就是我为我所做的工作:
Private Sub Pre_Load() Dim sBasePath As String = AppDomain.CurrentDomain.BaseDirectory Dim sAllFiles() As String = Directory.GetFiles(sBasePath) For Each sAssemblyFile As String In sAllFiles If sAssemblyFile.EndsWith(".dll") Then If Not Me.HasThisAssembly(sAssemblyFile) Then Assembly.Load(AssemblyName.GetAssemblyName(sAssemblyFile)) End If End If Next End Sub Private Function HasThisAssembly(ByVal vsAssemblyName As String) As Boolean For Each oAssembly As Assembly In AppDomain.CurrentDomain.GetAssemblies() Dim oFile As New FileInfo(vsAssemblyName) If oFile.Name = oAssembly.GetName().Name + ".dll" Then Return True Exit Function End If Next Return False End Function