在运行时加载2个版本的程序集

时间:2009-07-27 17:01:26

标签: c# appdomain

在过去的几周里,我一直试图破解这个,但还没有找到一个好的解决方案;希望我能在这里得到答案。

我有两个程序集(ZA和ZB),它们都指向一个公共项目/ dll(ZC),但它们可以是不同的版本(即相同的dll名称,相同的名称空间,某些类可能不同) 。但是,如果一个程序集在运行时由另一个程序集加载(例如A加载B),那么每个程序集都可以自行工作,那么我就无法使它工作。需要一些帮助。

以下是设置:

  • ZA依赖于ZC(通用)版本1.1
  • ZB取决于ZC版本1.0

ZA需要在运行时加载需要在ZB中加载某些内容(这取决于ZC)。

ZA是主应用程序。 在bin目录下,有一个插件目录plugins/plugin-ZB,我希望在其下放置所有ZB及其依赖项(ZC)。

这是我到目前为止所尝试的内容:

Assembly.Load()使用相同版本的dll - 工作正常。

Assembly.Load()使用不同版本的dll - ZB加载,但是当方法运行时,我得到一个找不到异常的方法。

AppDomain.Load()找不到文件错误;我甚至使用委托来解决集合。

有关ZC的一些细节: - 一些方法是公共静态(有些不是)。例如。 Log.Log("hello"); - 有些人可能会返回值(基元或对象)。 - 某些方法是非静态的(和返回值)。

帮助? - TIA

3 个答案:

答案 0 :(得分:3)

    m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll"))
    m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll"))

    Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString)
    Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString)

    m_OldObject = m_Assembly1.CreateInstance("FullClassName")
    m_NewObject = m_Assembly2.CreateInstance("FullClassName")

从现在开始,我使用后期绑定和/或反射来运行我的测试。

.NET: Load two version of the same DLL

答案 1 :(得分:1)

除了Jonathan Allen的优秀建议外,解决问题的更“经典”方法是在2个不同的AppDomanis中加载2个版本。然后,您可以使用.NET Remoting使两个AppDomains通信。所以ZA应该在这个AppDomain ZB中创建一个新的Appdomain,Load并通过Remoting在ZB中调用一些操作。

请注意,.NET Remoting对您要使用的类有一些要求(从MarshalByRef继承),而创建AppDomain是一项昂贵的操作。

希望这个帮助

答案 2 :(得分:0)

我同时加载了同一个程序集的两个版本。它就像你描述的那样发生了。

您必须说服运行时为ZA和ZB加载相同版本的ZC。我找到了两种方法:

  1. 在App.config文件中使用bindingRedirect元素。 this question中有一些详细信息。
  2. 使用AppDomain.AssemblyResolve事件。 this answer中有一些详细信息。
  3. AppDomain.AssemblyResolve的唯一问题是它只在运行时找不到请求的版本时触发。如果两个版本都可用,那么您必须使用bindingRedirect。我使用了AppDomain.AssemblyResolve事件,然后添加了一个安全检查,通过查看程序集的引用程序集集来确保加载了正确的版本。如果不是,我向用户抱怨该库的旧版本就在它周围并告诉它们它在哪里。