获取程序集而不实例化它们

时间:2012-03-30 17:42:27

标签: c# .net vb.net assemblies

我正在尝试使用CurrentDomain将所有程序集放入AppDomain.CurrentDomain.GetAssemblies()FullName写入DropDownList,但是如果我没有实例化它们,则它们不是在GetAssemblies()中的CurrentDomain返回的数组中看到。

它们都作为参考添加到解决方案的Reference文件夹中。只有当我第一次实例化时才能从GetAssemblies()获取它们。

如何以简单且更通用的方式克服此问题,而不是每次添加新的程序集等时实例化它们。

根据公司政策,我必须对图像的某些部分进行模糊处理:

enter image description here

参考文件夹中引用了所有组件:

enter image description here

3 个答案:

答案 0 :(得分:7)

除了其他人的评论之外,其他地方确实发生了一些微妙的事情。

VisualStudio实际上将.dll引用添加到构建程序集的反射信息的程序集清单中,除非实际使用它们。

作为示例,创建一个新项目,并引用一个程序集。我以nunit.framework.dll为例。

但实际上并没有使用它。我的代码很简单:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

但Project 确实在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中有一个外部。这也提供反射,因此它知道要加载的依赖程序集。

过去那个小细节,正如其他人所说,运行时实际上并没有加载一个程序集,直到第一次需要它,因此你的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

答案 1 :(得分:3)

在实例化类型或依赖类型之前,它们不会被加载。因此,如果您的项目引用了大量的程序集但没有实例化其中的任何类型,那么您的应用程序不会产生从磁盘上加载这些位的性能。

如果您想了解项目引用的程序集,则必须使用.NET Reflection探索程序集。具体来说,我建议你看一下Assembly.GetReferencedAssemblies()方法。

HTH。

答案 2 :(得分:-1)

这就是我为我所做的工作:

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