加载不同版本装配成单独的AppDomain [英] Load different version of assembly into separate AppDomain

查看:219
本文介绍了加载不同版本装配成单独的AppDomain的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我采取了支持插件的应用程序。目前,当我尝试由主机应用程序和插件同时使用负载常见的装配问题出现了:主机应用程序应当使用该程序集的一个版本,而插件使用另一个版本这是通过应用程序的升级决定。流程 - 插件,可以独立于主机应用程序进行更新

I'm implementing application that supports plugins. Currently the problem arises when I try to load common assembly that is used both by host application and plugin: host application should use one version of that assembly, while plugin uses another version. This is dictated by application upgrade process - plugin can be updated separately from host application.

每一个组件签约,所以我用强名称加载程序集。

Every assembly is signed, so I use strong names for loading assemblies.

我创建了一个测试应用程序,它演示了此问题。插件程序集位于主机应用程序的子文件夹插件。插件文件夹包含插件实现DLL,插件声明接口DLL和CommonLib DLL。主机应用程序也可以使用插件声明DLL和CommonLib DLL(文件夹树位于1级以上)。

I created a test application which demonstrates the problem. Plugin assemblies are located in subfolder 'Plugin' of host application. Plugin folder contains the plugin implementation DLL, plugin declaration interface DLL and CommonLib DLL. Host application also use plugin declaration DLL and CommonLib DLL (located 1 level up in folder tree).

下面是插件加载源$ C ​​$ C:

Here is source code of plugin loading:

static void Main(string[] args)
{
    Console.WriteLine("Host   says: {0}", GreetingManager.SayHello("Sasha"));
    Console.WriteLine("Host   says: {0}", GreetingManager.SayGoodBye("Sasha"));
    var pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugin");
    var pluginFile = Directory.GetFiles(pluginDir).First(f => f.EndsWith("Plugin.dll"));

    Assembly asmr = Assembly.ReflectionOnlyLoadFrom(pluginFile);

    AppDomain pluginDomain = AppDomain.CreateDomain("Plugin", null, pluginDir, "", false);

    pluginDomain.Load(asmr.FullName);

    Assembly asm = pluginDomain.GetAssemblies().First(a => a.GetName().Name == "Plugin");
    Type p = asm.GetTypes().First(t => t.GetInterfaces().Contains(typeof(IPlugin)));

    var pluginInstance = (IPlugin)pluginDomain.CreateInstanceAndUnwrap(asm.FullName, p.FullName);
    Console.WriteLine("Plugin says: {0}", pluginInstance.TransformString("Sasha"));
}

它抛出异常:

It throws exception:

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'CommonLib, Version=1.0.9.0, Culture=neutral, PublicKeyToken=73c7c163a33b622c' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
   at Plugin.MyPlugin.TransformString(String str)
   at PluginBackwardCompatibilityTest.Program.Main(String[] args) in D:\Projects\Test\PluginBackwardCompatibilityTest\PluginBackwardCompatibilityTest\Program.cs:line 37

正如我udnerstand,插件仍然试图找到在宿主应用程序文件夹CommonLib组件(忽略创建的AppDomain时,我提供的appBasePath参数),但发现旧的版本1.0.8有与产生此错误。 我怎样才能迫使插件从插件文件夹中加载引用的程序集 - 有没有办法指定完整装配路径使用强名称时加载

As I udnerstand, plugin still tries to find CommonLib assembly in the host application folder (ignoring the appBasePath parameter I provided when creating AppDomain), but finds older version 1.0.8 there and generates this error. How can I force plugin to load referenced assemblies from Plugin folder - there is no way to specify full assembly path to load when using strong name.

推荐答案

我觉得你的问题如下:

Assembly asm = pluginDomain.GetAssemblies().First(a => a.GetName().Name == "Plugin");
Type p = asm.GetTypes().First(t => t.GetInterfaces().Contains(typeof(IPlugin)));
var pluginInstance = (IPlugin)pluginDomain.CreateInstanceAndUnwrap(asm.FullName, p.FullName);

通过这个你加载更新/过时的类型引用到主应用程序域(其中有一个不同的版本已加载的程序集)。

With this you're loading the updated/outdated type references into the main AppDomain (which has the assembly already loaded in a different version).

我建议您使用以下方法:

I recommend you use the following approach:

  1. 创建一个包含合同/接口一个单独的程序。本届大会是固定并保持在一个特定版本的所有时间,它永远不会过时,每一个版本的插件可以参考它。
  2. 在编写一个程序集加载器是您的主机应用程序的一部分,但在一个单独的装配以及。该组件加载器组件不得有任何引用到应用程序的其他部分,所以你可以将它设置在新的AppDomain。
  3. 建立新的应用程序域后,加载AssemblyLoader的一个实例。这一次加载插件组件,并与其进行交互。
  4. 您的应用程序不与大会本身进行交互。您的应用程序通过应用程序域边界调用你AssemblyLoader和AssemblyLoader调用插件

我不能说这是否是最好的版本可能的,但是这一次的作品pretty的很好,我在每个插件可以将任何版本的任何组件的环境。有了这个设置你pretty的耐多对不断变化的版本或更新,每一个插件,可以使用它想要的版本。

I can't say if this is the best version possible, but this one works pretty well for me in an environment where each plugin can load any version of any assembly. With this setup you're pretty much resistant to changing versions or updates and each plugin can use the version it wants.

让我知道,如果你的作品。

Let me know if it works for you.

这篇关于加载不同版本装配成单独的AppDomain的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆