加载相同dll的不同版本,但依赖项也不同?

时间:2018-05-18 11:02:53

标签: c# dll .net-assembly

想象一下场景,A.dll和B.dll,A.dll引用B.dll并调用驻留在B.dll中的方法。

在未来的某个时刻,你有两个不同版本的A.dll和B.dll(为什么会出现这种情况并不重要)。您希望能够在同一个应用程序中使用这些dll的两个版本。

我遇到的问题是我可以加载Av1.dll和Av2.dll但他们最终都使用Bv1.dll。

所以我想要的是:

Av1.dll --> Bv1.dll
Av2.dll --> Bv2.dll

但正如我所说,我最终得到的是:

Av1.dll --> Bv1.dll
Av2.dll --> Bv1.dll

AppDomains不可行,因为每个输入和输出都需要实现MarshalByRefObject,因此它们最终变得难以操作。

即使他们有点古怪,我也会接受创造性的解决方案。这更像是一个学术问题,所以不要因为重构你在现实世界中需要做的dll或一些软糖而陷入困境,将其视为挑战。

有可能吗?就像你可以在幕后动态检查,重写和重新编译dll,但是替换引用,实际上是:

A.dll --> B.dll
C.dll --> D.dll

正如我所说,我对创造性解决方案持开放态度。

修改

好的,也许一个更清晰的例子会有所帮助。

让我们想象一下,第三方为您提供了计算所得税的图书馆。该库由相互引用的dll组成。

所以在正常情况下你有:

TaxHelper helper = new TaxHelper();
var result = helper.CalculateIncomeTax(...params...);

但是,让我们想象,在下一个纳税年度,您的第三方会为您提供新版本的图书馆,因为新税务年度的规则已经更改,但您还必须能够计算税额。往年。他们所做的就是更改代码并重新编译,所有类和dll名称都是相同的。

所以我一直在尝试的是沿着这些方向发展的事情(这只是我的头脑,所以可能不是100%正确):

Assembly taxHelper1Assembly = Assembly.LoadFrom(...path1...);
Assembly taxHelper2Assembly = Assembly.LoadFrom(...path2...);

Type taxHelper1Type = taxHelper1Assembly.GetType(...);
Type taxHelper2Type = taxHelper2Assembly.GetType(...);

dynamic taxHelper1 = Activator.CreateInstance(taxHelper1Type);
dynamic taxHelper2 = Activator.CreateInstance(taxHelper2Type);

var result1 = taxHelper1.CalculateIncomeTax(...params...);
var result2 = taxHelper2.CalculateIncomeTax(...params...);

现在这可行,直到某一点,taxHelper1taxHelper2都是不同的版本,并会返回不同的结果......但是......虽然顶级TaxHelper类不同,但在内部他们引用其他dll作为依赖项,taxHelper1引用了正确的依赖项,因为它们是先加载的,taxHelper2还引用了taxHelper1个依赖项。

修改2

想想我在这个帖子中找到了答案:Loading Dependent Assemblies Manually

1 个答案:

答案 0 :(得分:0)

在这里,这可能足以让你入门。它被称为依赖注入,正如您在问题的评论中提到的那样。你应该读一读。

这里我在A.dll中定义了两种类型。其中一个是定义B的合同的接口:

public interface IDependencyB
{
    string Name { get; }
}

这是我的A课程。它的构造函数需要IDependencyB

public class A
{
    public A(IDependencyB dependencyB)
    {
        System.Diagnostics.Debug.Print(dependencyB.Name);
    }
}

然后,您可以在单独的程序集中定义两个(或多个)类的变体,如果您愿意,可以实现该接口:

class B1 : IDependencyB
{
    public string Name => "B1";
}

class B2 : IDependencyB
{
    public string Name => "B2";
}

你可以这样测试:

var b1 = new B1();
var b2 = new B2();
var a1 = new A(b1);
var a2 = new A(b2);

这是一个非常基本的例子,但我认为它应该让你朝着正确的方向前进。