插件可更换组件

时间:2014-02-05 16:58:44

标签: c# mef system.componentmodel

我们正在尝试热交换(更新)程序集,正常的工作流程是我们进行一些更改,构建程序集,进行一些更改并再次构建,在理想的世界中,主机应用程序将获得新版本的程序集(使用更新的类型)。

这是我们的小插件加载器类:

public class PluginLoader<T>
{
    private CompositionContainer _compositionContainer;
    private RegistrationBuilder _registrationBuilder;
    private DirectoryCatalog _catalog;

    [ImportMany(AllowRecomposition = true)]
    public IList<T> Plugins { get; set; }

    public PluginLoader(string pluginsDirectory)
    {
        Plugins = new List<T>();
        SetShadowCopy();

        _registrationBuilder = new RegistrationBuilder();
        _registrationBuilder
           .ForTypesDerivedFrom(typeof(T))
           .SetCreationPolicy(CreationPolicy.NonShared)
           .Export<T>();

        _catalog = new DirectoryCatalog(pluginsDirectory, _registrationBuilder);

        _compositionContainer = new CompositionContainer(_catalog, CompositionOptions.DisableSilentRejection);
        _compositionContainer.ComposeParts(this);
    }

    public void Reload()
    {
        _catalog.Refresh();
        _compositionContainer.ComposeParts(this);
    }

    private static void SetShadowCopy()
    {
        AppDomain.CurrentDomain.SetShadowCopyFiles();
        AppDomain.CurrentDomain.SetCachePath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "ShadowCopyCache"));
        AppDomain.CurrentDomain.SetShadowCopyPath(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Plugins"));
    }
}

我们有代码来识别使用FileSystemWatcher放入plugins文件夹的新插件,当发生这种情况时我们会调用Reload,但是新版本的程序集实际上并未加载。 有什么指针吗?

注意:

  • 没有识别出新的或删除的类型,就像它根本无法识别新的程序集一样。
  • 我们检查过,也没有任何构图和其他错误,所以我们有点迷失:D
  • 重要的是要注意,如果我们使用不同的编译器(Roslyn)构建相同的无法识别的程序集,那么它就会被识别(这表示没有任何设置错误,只是程序集需要以某种方式不同)

1 个答案:

答案 0 :(得分:1)

不推荐使用SetShadowCopy中调用的方法。您无法在现有AppDomain上启用ShadowCopy。有关如何在新AppDomain上启用ShadowCopy的示例,请查看此answer

DirectoryCatalog.Refresh会更新已加载的程序集。它仅检查文件删除和添加。看看这个answer的粗略解决方法。请注意,我不确定这种方法是否是线程安全的或生产就绪的,因为我只测试了简单的场景。另一种方法是创建自己的DirectoryCatalog,它也可以处理更新。 MEF源代码可用(与框架的其余部分一样)。棘手的部分是线程安全,因为DirectoryCatalog实现使用Microsoft的内部类进行锁定。