5

我的 C# 项目引用了两个第三方 DLL。这很重要,因为这意味着我无法访问源代码,也无法修改或重新编译这两个 DLL。

我们称它们为 dll A 和 dll B。这是 dll A 的样子:

namespace ThirdParty.Foo
{
  public class Bar
  {
    ...snip...
  }

  public class Something
  {
    public Bar MyProperty { get; set; }
  }
}

这是 dll B 的样子:

namespace ThirdParty.Foo
{
  public class Bar
  {
    ...snip...
  }

  public class SomethingElse
  {
    public Bar MyProperty { get; set; }
  }
}

如您所见,它们具有相同的命名空间,并且它们都定义了一个具有相同名称的类。我的 C# 代码需要引用这两个 DLL。我使用引用上的别名属性来区分这两个引用,并且我还在extern alias firstDllextern alias secondDll的 C# 文件的顶部。到目前为止,一切都很好。

对我来说很明显的类型Something.MyProperty是 firstDll.ThirdParty.Foo.Bar 和类型SomethingElse.MyProperty是 secondDll.ThirdParty.Foo.Bar 但由于某种原因,Visual Studio 感到困惑并将两个属性的类型解析为同一个Bar类第一个DLL。

有没有办法让我“强制”VisualStudio 解析正确的类型?

编辑:我在 Visual Studio 中遇到的错误是:无法将类型 'ThirdParty.Foo.Bar [d:\MySolution\References\Second.dll]' 隐式转换为 'ThirpParty.Foo.Bar [d:\MySolution\References \First.dll]'

4

6 回答 6

5

创建一个用作 DLL A 包装器的 DLL。我们将新的 DLL 称为“C”。然后,您的项目将引用 DLL B 和 C。

于 2013-08-06T23:23:22.547 回答
2

如果这两种类型具有相同的名称和命名空间,那么您几乎会陷入困境。在 C# 中,名称/标识符非常重要,“最适合”仅在特殊情况下有效。

但是,您可以为这两种不同类型编写包装器,并使这些包装器具有不同的名称。通过为包装器设置两个不同的(甚至一个)项目,您可以只有一个引用,从而有效地“强制”解决冲突。

于 2013-08-06T23:24:58.990 回答
2

有效的东西(对我来说它确实正确引用了)如下,首先(你可能已经这样做了)单击引用中的每个 dll 并分配一个别名并放置正确的外部别名。之后使用类 Something 和 SomethingElse(以及正确分配 Bar 属性)为每个类(Something 和 SomethingElse)创建一个类并从它们派生并隐藏 MyProperty 属性:

public class TestFirst : first.ThirdParty.Foo.Something
{
    //here you shadow and since you must provide the alias
    //and the fully qualified name it will bet set to the
    //right Bar class,same bellow in testsecond.
    public first.ThirdParty.Foo.Bar MyProperty { get; set; }
}

public class TestSecond : second.ThirdParty.Foo.SomethingElse
{
    public second.ThirdParty.Foo.Bar MyProperty { get; set; }
}

照常营业后:

TestSecond t = new TestSecond();
t.MyProperty = new second.ThirdParty.Foo.Bar();
于 2013-08-07T01:27:36.123 回答
1

由于这里有一个极端情况,两个程序集不仅具有相同的命名空间,而且具有相同的完整程序集名称(意味着类型具有相同的程序集限定名称),您可能需要考虑更极端的措施来解决它。如果它是一个完全托管的 DLL(没有混入本机代码)并且不是强命名的(或者您可以删除强命名),您可以通过这样的过程摆脱困境:

  1. 运行ildasm并输出到磁盘上的 .il 文件。
  2. 使用仔细搜索和替换来修改 .il 文件以更改所有类型的根命名空间(注意内部命名空间或包含与根命名空间相同文本的类型名称。)
  3. 通过ilasm运行修改后的文件,以使用更改构建一个新的 .dll。
于 2013-08-08T13:26:12.840 回答
1

我将通过 Assembly.Load 显式加载 dll,然后对您需要的类型执行 createinstance,然后通过动态调用方法——那是因为我很懒。另一种(不是懒惰的)方法是使用反射来找到方法并调用它。

于 2013-08-07T00:08:46.263 回答
0

您可以使用关键字var而不是显式指定类型以避免模糊引用

var x = new ThirdParty.Foo.Something();
var y = new ThirdParty.Foo.SomethingElse();

var barX = x.MyProperty;
var barY = y.MyProperty;
于 2013-08-06T23:37:09.767 回答