1

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

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

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)构建相同的无法识别的程序集,那么它就会被识别(这表明没有任何错误的设置,只是程序集需要以某种方式有所不同)
4

1 回答 1

1

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

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

于 2014-02-06T12:54:15.893 回答