类型存在于2个程序集中


75

我已经从两个不同的第三方COM DLL创建了两个.NET Interop程序集。两个COM DLL都包含一个名为的类型COMMONTYPE。因此,COMMONTYPE现在也通过两个Interop组件公开了。

我有第三个项目需要使用这两个Interop程序集,并且得到了臭名昭著的编译时错误:

该类型同时<ABC>存在于<ASSEMBLY1.dll><ASSEMBLY2.dll>

由于COM DLL是由第三方供应商提供的,因此我无法访问源代码,并且正在编写C#控制台应用程序,这意味着我没有可在其中添加debug=false解决方法的web.config文件。我能做什么?


我来到这里是因为Visual Studio中被抱怨JsonConvert中都存在Newtonsoft.Json.Torq和Newtonsoft.Json类型
马修

Answers:


164

我知道这很旧,但是有一种比列出的方法更简单的方法。当您引用共享名称和名称空间完全相同的类型的两个程序集时,此方法有效。

如果右键单击对DLL的引用,然后选择“属性”,则会看到这里是一个名为“别名”的属性。

在此处输入图片说明

默认值为“ global”。对于一个有冲突的程序集,请将其更改为任何其他值。在下面的示例中,我将其从“全局”更改为“目标”。

接下来,在代码文件中,您将必须使用extern关键字将此别名用作这些类型的根级名称空间。在此示例中,应将以下内容放在.cs文件的顶部:

extern alias destination

现在,在此文件中,您可以引用这两种类型。

extern alias destination;
namespace Test
{
    public static class TestClass
    {
        public static void Success()
        {
            var foo = destination::Some.Duplicate.Namespace.SomeDuplicateType();
            var bar = Some.Duplicate.Namespace.SomeDuplicateType();
        }
    }
}

1
赞赏更好的答案!显然,这基本上是别名的意思
PandaWood

4
对我来说,绝对也是最佳答案。其他解决方案甚至不起作用,因为我有两个完全相同的dll,一个仅与ILMerge合并在另一个中。问题已解决
Johnny

我想在这里从@bunkerdive重新提问(最受欢迎的答案):如何通过NuGet软件包使用它?如果您尝试更改Alias VS,则会出现错误:无法修改源自导入文件的评估对象
Geordie

1
我进入参考资料,选择了Nuget安装的软件包,然后将别名设置为destination。像魅力一样
运作

1
@PedroGaspar可能是因为您使用的是Visual Studio“社区”。我在VS2017 Enterprise上,我刚刚在5秒钟前实现了。某些较低级别的VS对单元测试没有很好的支持。
AlbatrossCafe

13

除非供应商的名称空间相同(不太可能),否则此时的类型定义实际上是分开的。您需要做的(有时是完整的PITA)是在using语句中创建名称空间别名,而不是简单地应用carte blanche语句。这将允许您重新标识名称空间:

using Vendor1 = Vendor.Namespace;
using Vendor2 = OtherVendor.Namespace;

...

Vendor1.COMMONTYPE blah = new Vendor1.COMMONTYPE();
Vendor2.COMMONTYPE blah2 = new Vendor2.COMMONTYPE();

这将意味着为这些供应商的每个名称空间中的所有类型使用特定的别名。


这肯定会帮助我解决编译时错误。但是,在创建程序集时,我没有什么办法使.NET忽略特定类型,以便仅在其中一个程序集中使用通用类型。
Kou S Hal '02

1
@KouSHal:唯一的方法是建立一个包装类,该包装类引用一个供应商库并将所有类,扩展方法等公开为代理。如果它是一个只有几个类的小型库,这不会太难,但是如果像大多数供应商库一样,这将是创建噩梦且难以维护的。
乔尔·埃瑟顿

13

问题仍然存在,但找到了一个更简单的选项...选择要使用的引用...在属性下,将别名更改为'xyz'现在在代码行中,在顶部添加:

extern alias xyz;

然后使用添加:

using xyz.VENDOR2.Type;

或另一种使用方式:

using OtherNameSpace = xyz.VENDOR2.Type;

现在您应该可以显式使用引用,如下所示:

var abc = new xyz.VENDOR2.Type.abc();

要么

var abc = new OtherNameSpace.abc();

4
但是,当引用的是NUGET包而不是常规dll时,如何实现呢?
bunkerdive

@bunkerdive无论有没有NuGet软件包,它几乎都可能以相同的方式工作。当您安装NuGet程序包时,对该程序包中程序集的引用应自动添加到Visual Studio项目中。看看下面引用的*解决方案资源管理器”视图窗格中项目下的节点。
肯尼Evitt

1

您可以对不同的名称空间和/或类型使用别名:

看起来像这样:

using other = sssssss.a;
namespace ConsoleApplication1
{
    public class a 
    {
        public string ff { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            other s = new other();
            a b = new a();
        }
    }
}
namespace sssssss 
{

    public class a
    {
        public string ff { get; set; }
    }
}

MSDN


0

也许您可以通过更改namespace其中一个程序集来欺骗它,在这种情况下,一个程序集的完全限定名称COMMONTYPE将不等于另一个,并且可能可以解决您在第3个DLL中发生冲突的问题。

希望这可以帮助。


不幸的是,我无法使用tlbimp从现有的COM dll生成.NET程序集。
Kou S Hal '02

0

我知道这很旧,但最近遇到了这个问题。我发现解决此问题的最佳方法是YourProjectName.csproj通过添加以下内容来修改文件:

<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
    <ItemGroup>
        <ReferencePath Condition="'%(FileName)' == 'Namespace.You.Want.To.Alias'">
            <Aliases>NewAliasForNamespace</Aliases>
        </ReferencePath>
    </ItemGroup>
</Target>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.