【问题标题】:Is it possible to switch DLLs at runtime so as to use a different version?是否可以在运行时切换 DLL 以使用不同的版本?
【发布时间】:2015-07-08 10:42:05
【问题描述】:

我有一个包含许多插件 (MEF) 的应用程序,这些插件连接到许多不同的 I/O 设备。这些插件中的大多数都有许多托管和非托管 dll。

一家制造商最近发布了新固件和新驱动程序。 API 保持不变。

我认为我可以将两个 dll 版本包含在单独的资源文件夹中,并在应用程序启动时将所需的集合复制到输出文件夹中。

(我想我可以制作插件的第二个副本并找出一种加载正确的方法,但我认为复制 DLL 可能更容易——尤其是考虑到插件代码没有改变 em>)

这不起作用。

static MyClass() // static constructor
{
    // required version?
    if (envvar.Equals("4") )
    {
        path = "ver4.1.1";
    }
    else
    {
        path = "ver2.5.1";
    }

    // location of drivers
    path = Path.Combine("./Prj/QX", path);
    string[] files = Directory.GetFiles(path);

    // Copy the files and overwrite destination files if they already exist.
    foreach (string s in files)
    {
        string fileName = Path.GetFileName(s);
        string destFile = Path.Combine(".", fileName);
        File.Copy(s, destFile, true);
    }

    // force load of assemby
    Assembly assy = LoadWithoutCache("driver.dll");
    string fn = assy.FullName;
}

static Assembly LoadWithoutCache(string path)
{
    using (var fs = new FileStream(path, FileMode.Open))
    {
        var rawAssembly = new byte[fs.Length];
        fs.Read(rawAssembly, 0, rawAssembly.Length);
        return Assembly.Load(rawAssembly);
    }
}

错误消息表明原始 DLL 已加载或应该已加载但无法加载。

Could not load file or assembly 'driver, Version=1.5.77, Culture=neutral, PublicKeyToken=983247934' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

有什么方法可以实现我的目标,还是我必须构建我的应用程序的 2 个单独版本?

编辑 我还应该说,没有必要同时加载两个 DLL。使用导致加载一个或另一个 DLL 的参数启动应用程序就足够了。

【问题讨论】:

标签: c# .net dll


【解决方案1】:

也许您可以在运行时通过如下反射加载您的 dll:Loading DLLs at runtime in C#

但我怀疑它是否可用于更大的项目

【讨论】:

    【解决方案2】:

    You could do it in several ways. 一种可能性是使用Managed Extensibility Framework (MEF)。 您甚至可以监控 dll 所在的文件夹,并在新版本可用时立即加载。

    另一种可能是你可以使用reflection在运行时动态加载你想要的dll。

    【讨论】:

      【解决方案3】:

      实现此目的的一种(复杂)方法是:

      1。使用 FileSystemWatcher(FSW) 监视文件夹

      FSW 检测程序集是否被更改或删除。

      2。将程序集加载到Reflection-Only Context

      只能检查加载到此上下文中的程序集! 通过获取程序集的类型并检查这些类型是否实现了您的 PluginInterface,确保程序集类型实现了 PluginInterface。

      3。使用 Shadow Copying 将程序集加载到单独的 AppDomain 中

      由于您只能卸载 AppDomain 及其所有程序集,因此您将每个插件程序集加载到其自己的 AppDomain 中。这样只需卸载插件的 AppDomain。

      一定要终止插件的所有进程/线程!

      影子复制通过将程序集复制到临时路径来确保原始文件的更改。

      4。跟踪加载的程序集

      将成功加载的程序集的路径放入列表中。 这样可以更轻松地检测程序集是否需要加载/重新加载。

      5。处理 FSW 事件

      检查哪个 .dll 已更改/删除以卸载程序集,或者是否检测到新程序集以加载它。

      6。转到第 2 步


      您好, 黑眼圈

      【讨论】:

      • 影子复制是热插拔 MEF 程序集的正确方法
      • @plast1k 但是您仍然必须在各个应用程序域中加载插件。 Shadow Copying 会加载原件的“副本”,使您能够更改原件,但 MEF 不会加载已更改的原件。它仍然使用副本。 MEF 无法卸载/重新加载单个程序集。只能卸载 appdomain 的所有程序集。
      • 我同意,抱歉,我主要只是指出其他答案没有讨论的内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多