Is it possible to switch DLLs at runtime so as to

2019-06-23 22:32发布

I have an application which contains a number of plugins (MEF) which connect to a number of different I/O devices. Most of these plugins have a number of managed and unmanaged dlls.

One manufacturer has recently released new firmware and new drivers. The API remains the same.

I thought that I could include both dll versions in separate resource folders and copy the required set into the output folder when application starts up.

(I guess I could just make a second copy of the plugin and figure out a way of loading the correct one but I thought that copying the DLLs might be easier - especially considering that the plugin code is unchanged)

This does not work.

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);
    }
}

The error message suggests that the original DLL was loaded or should have been loaded but could not be.

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)

Is there any way to achieve my goal or do I have to build 2 separate versions of my application?

EDIT I should also say that it is not necessary to have both DLLs loaded at the same time. It would be enough to start the application with a parameter which causes one or the other DLL to be loaded.

标签: c# .net dll
3条回答
手持菜刀,她持情操
2楼-- · 2019-06-23 22:44

You could do it in several ways. One possibility would be to use the Managed Extensibility Framework (MEF). You could even monitor a folder where the dlls reside and load a new version as soon as a new one becomes available.

The other possibility is that you can use reflection to dynamically load the dll you want during runtime.

查看更多
Lonely孤独者°
3楼-- · 2019-06-23 22:51

Maybe you could load your dlls at runtime via reflections like this: Loading DLLs at runtime in C#

but i doubt it is usable for a bigger project

查看更多
再贱就再见
4楼-- · 2019-06-23 23:11

One (complicated) way to achieve this is:

1. Use a FileSystemWatcher(FSW) to watch a Folder

The FSW detects if an assembly gets changed or deleted.

2. Load an assembly into the Reflection-Only Context

Assemblies loaded into this context can only be examined! Make sure the assembly type implements the PluginInterface, by getting the types of an assembly and checking if the types implement your PluginInterface.

3. Load assembly into a seperate AppDomain using Shadow Copying

Because of the fact that you can only unload an AppDomain with all it's assemblies, you load each plugin assembly in its own AppDomain. This way the just unload the plugin's AppDomain.

Be sure to terminate all processes/threads of the plugin!

Shadow copying ensures the change of the original file by copying the assembly into a temporary path.

4. Keep track of loaded assemblies

Put the path of a successfully loaded assembly into a list. This makes it easier to detect if an assembly needs to get loaded/reloaded.

5. Handling FSW events

Check which .dll was changed/deleted to unload the assembly, or if a new assembly was detected to load it.

6. Goto step 2


Greetings, Blackanges

查看更多
登录 后发表回答