我们正在尝试热交换(更新)程序集,正常的工作流程是我们进行一些更改,构建程序集,进行一些更改并再次构建,在理想的世界中,主机应用程序将获得新版本的程序集(使用更新的类型)。
这是我们的小插件加载器类:
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,但是新版本的程序集实际上并未加载。 有什么指针吗?
注意:
答案 0 :(得分:1)
不推荐使用SetShadowCopy
中调用的方法。您无法在现有AppDomain
上启用ShadowCopy。有关如何在新AppDomain上启用ShadowCopy的示例,请查看此answer。
DirectoryCatalog.Refresh会更新已加载的程序集。它仅检查文件删除和添加。看看这个answer的粗略解决方法。请注意,我不确定这种方法是否是线程安全的或生产就绪的,因为我只测试了简单的场景。另一种方法是创建自己的DirectoryCatalog,它也可以处理更新。 MEF源代码可用(与框架的其余部分一样)。棘手的部分是线程安全,因为DirectoryCatalog实现使用Microsoft的内部类进行锁定。