是否可以在运行时切换DLL以使用不同的版本?

pau*_*aul 5 .net c# dll

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

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

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

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

这不起作用.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

错误消息表明原始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)
Run Code Online (Sandbox Code Playgroud)

有没有办法实现我的目标,还是我必须构建我的应用程序的2个单独版本?

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

小智 5

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

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

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

2. 将程序集加载到仅反射上下文中

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

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

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

确保终止插件的所有进程/线程!

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

4. 跟踪加载的程序集

将成功加载的程序集的路径放入列表中。这使得更容易检测程序集是否需要加载/重新加载。

5. 处理 FSW 事件

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

6. 转到第 2 步


问候,黑甘斯


小智 0

也许您可以通过像这样的反射在运行时加载 dll:Loading DLLs at run in C#

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