.NET程序集引用101

时间:2010-06-20 04:33:21

标签: c# .net assemblies external-assemblies refix

我在Assembly A中有以下类。程序集引用了StructureMap 2.6.1。

public static class Bootstrapper
{
    public static void Bootstrap(string databaseName)
    {
        StructureMapBootstrapper.Bootstrap(databaseName);
    }
}

我在一个完全不同的程序集(B)中引用程序集A,并且在调用此行时遇到以下运行时错误:

Bootstrapper.Bootstrap(db);

运行时错误是:

FileNotFoundException:无法加载文件或程序集“StructureMap,Version = 2.6.1.0,Culture = neutral,PublicKeyToken = e60ad81abae3c223”或其依赖项之一。系统找不到指定的文件。

我经常不得不将StructureMap.dll复制到Assembly B的bin目录中。这非常令人讨厌。有关如何解决此问题的任何建议?有人知道AssemblyB需要AssemblyA引用的程序集的一般规则吗?

谢谢!


感谢您的快速回复!我想过简单地添加StructureMap作为参考。然而,我在设计中采用的角度是从消费者那里抽象出底层实现。换句话说,程序集B对于最终使用StructureMap这一事实一无所知。另外,如果我是GAC StructureMap,那么我会遇到部署问题吗?如果我将站点部署到其全局缓存中没有StructureMap的主机,那么我将回到原点。我很好奇,鉴于这个程序集引用问题,如何实现真正的抽象。

4 个答案:

答案 0 :(得分:2)

有一个名为Refix的优秀工具可用于检查和修复依赖项。

答案 1 :(得分:1)

为避免复制DLL,您可以将StructureMap.dll添加到项目中,并在构建AssemblyA时让VS自动将其复制到输出。

或者,您可以使用ILMerge将StructureMap.dll合并到程序集B中,而不必担心复制它,因为程序集B将包含所需的所有IL。

或者,您可以将StructureMap.dll添加到全局程序集缓存中,这应该允许.NET在不必复制的情况下找到它。但是,IIRC,所有GAC集会都需要强有力的名称。

答案 2 :(得分:0)

顺便说一句,由于程序集具有强名称(您可以通过它具有PublicKeyToken的值来看到这一点),您可以将StructureMap程序集安装到GAC中,将使它可用于系统上运行的任何.NET应用程序。这可能会解决您的问题。

至于在GAC中使用程序集进行部署,这取决于您计划部署的方式。我假设这是一个Winforms应用程序,所以我也假设你将通过一个安装项目进行部署。如果是这种情况,那么很容易在项目中包含应该放在GAC中的程序集,如果它不存在,它将安装在那里。

回答你的问题,程序集绑定和加载有些细微差别,但通用规则是在第一次加载包含的类型时加载程序集。只要引用的代码块位于活动堆栈帧上,就会加载类型。

最后一句话基本归结为:当发生以下任何一种情况时,会加载一个类型:

  • 加载另一种类型,使用有问题的类型作为实例或静态变量

例如,假设我有ABC类型。

public class A
{

}

public class C
{

}

public class B
{
    private A myA;
    private static C myC;
}

当加载类型B时,它也会加载A,因为它被用作实例变量,C将被加载,因为它被用作静态变量。

  • 将有问题的类型用作局部变量,参数或调用另一个将其用作参数的函数的函数。

答案 3 :(得分:0)

如果您希望程序集B不知道对StructureMap的依赖性,但也避免每次手动复制文件,您可以添加StructureMap作为程序集A的引用(正如其他人所说)并将两个项目的构建输出路径设置为相同的目录(通过Project Properties-> Build选项卡)。这样,当A组装也能“看到”它时。