.NET将类解析为错误的DLL

本文关键字:错误 DLL NET | 更新日期: 2023-09-27 18:26:49

我的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。我使用引用上的alias属性来区分这两个引用,我还在C#文件的顶部使用extern alias firstDllextern alias secondDll。到目前为止还不错。

在我看来,Something.MyProperty的类型是firstDll.ThrdParty.Foo.Bar,SomethingElse.MyProperty的类型是secondDll.TherdParty.Foo.Bar,但由于某种原因,Visual Studio混淆了这两个属性的类型,并将其解析为firstDll中的同一个Bar类。

有没有一种方法可以"强制"VisualStudio解析正确的类型?

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

.NET将类解析为错误的DLL

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

如果这两种类型具有相同的名称和命名空间,那么您将陷入困境。在C#中,名称/标识符非常重要,"最佳匹配"只适用于特殊情况。

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

有效的方法(对我来说,它确实正确引用了)如下:首先(可能已经这样做了)单击引用中的每个dll,并分配一个别名并放置正确的外部别名。在使用Something和SomethingElse类(并正确分配Bar属性)之后,为这些类中的每一个创建一个类(Something和SometingElse),并从中派生并隐藏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();

我会通过Assembly显式加载dll。load然后对所需的类型执行createinstance,然后通过dynamic调用方法-这是因为我很懒。另一种(不是懒惰的)方法是使用反射来找到方法并调用它

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

  1. 运行ildasm并输出到磁盘上的.il文件
  2. 使用仔细的搜索和替换来修改.il文件,以更改所有类型的根命名空间(对于内部命名空间或包含与根命名空间相同文本的类型名称,请小心)
  3. 通过ilasm运行修改后的文件以使用更改构建新的.dll

您可以使用关键字var而不是显式指定类型,以避免不明确的引用

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