使用两个具有相同名称和相同名称空间的DLL

时间:2010-12-14 23:05:42

标签: c# .net-3.5

我有一个项目需要引用两个具有相同名称的DLL。这些DLL名称不强,名称相同。

我需要访问每个DLL中的某些类型,但这些类型具有相同的完全限定名称。 所以我们假设第一个是带有someProduct.Type1和的公司DLLL.dll 第二个是带有someProduct.Type1的companyDLL.dll。

如何访问同一项目中的两个Type1类?

我已经尝试过使用extern alias,但它要求我更改其中一个DLL的名称。

5 个答案:

答案 0 :(得分:10)

如果您的两个DLL具有相同的名称,则必须重命名它们。例如Assembly1.dll和Assembly2.dll。

像往常一样在项目中添加这些DLL作为引用,并在每个引用的属性中指定别名。

使用DLL时代码中的

使用extern alias指定要引用的dll。

extern alias Assembly1Reference;
using Assembly1Reference::AssemblyNamespace.MyClass;

如果你这样离开,你很可能会得到一个FileNotFoundException说它无法加载文件或程序集。要解决此问题,您需要添加一个ResolveEventHandler,它将加载您尝试使用的正确程序集。为此,您必须准确指定存储DLL文件的位置。在下面的例子中,我手动将Dll文件复制到项目调试文件夹。如果它显示“assembly1的名称”,您可以在引用DLL,构建项目并使用记事本打开csproj文件后找到该名称。要查找的内容将在我的示例代码下面。

extern alias Assembly1Reference;
extern alias Assembly2Reference;

static void Load()
{
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    Do();
}

static void Do()
{
    new Assembly1Reference.Assembly.Class();
    new Assembly2Reference.Assembly.Class();
}

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string currentPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
    if(args.Name == "Name of assembly1")//Found in csproj file after referenced and built
    {
        return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(currentPath, "Assembly1.dll"));
    }
    if(args.Name == "Name of assembly2")//Found in csproj file after referenced and built
    {
        return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(currentPath, "Assembly2.dll"));
    }
    return null;
}

正如所承诺的,这是csproj文件中的引用。名称是include属性中的所有内容。

<Reference Include="MyAssembly_3.6.2.0, Version=3.6.2.0, Culture=neutral, PublicKeyToken=12341234asdafs43, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>Resources\Assembly1.dll</HintPath>
      <Aliases>Assembly1Reference</Aliases>
</Reference>

我知道这已经晚了但希望它能帮助从现在开始访问此页面的任何人。

答案 1 :(得分:3)

使用extern alias将程序集置于不同的名称空间中。如果您可以区分命名空间,则应该能够使用using altType1 = someProduct.Type1为该类型创建本地别名。

首先从命令行限定程序集:

/r:ProductA=companyDLLA.dll
/r:ProductB=companyDLLB.dll

然后使用extern alias

引用它们
extern alias productA;
extern alias productB;

最后,您可以为本地类型添加别名:

using productTypeA = productA.Type1;
using productTypeB = productB.Type1;

答案 2 :(得分:0)

我可以想到两种方法来解决这个问题。

  1. 将每个DLL加载到单独的AppDomain中。您必须通过AppDomain边界进行调用以触发各种属性和方法。

  2. 在加载程序集之前,反汇编然后重新组装每个程序集并将它们放入唯一(可能是动态生成的)名称空间。有一些工具可以帮助解决这个问题(1)(2)。你可以自动化它。

  3. 但我的基本感觉是,你真的不应该这样做。在上游解决这个问题比在已经编译的程序集之后解决它更容易。

答案 3 :(得分:0)

没有一个建议的解决方案对我有用。我必须重新编译这些DLL,并赋予它们不同的标识,即在项目设置中更改“程序集名称”。

如果无法重新编译DLL,则另一种解决方案是使用合适的名称创建包装器。

答案 4 :(得分:0)

遇到此问题时,我创建了两个不同的包装器项目,每个项目都引用了不同版本的dll,并使用Costura.Fody nuget以便将dll嵌入到包装器项目中,并防止内部版本冲突。 / p>