我试图阻止我的应用程序锁定 MEF 插件目录中的 DLL,以便我可以在运行时覆盖程序集(请注意,我实际上并没有尝试让 MEF 动态重新加载它们,在下一个应用程序启动时就可以了,我只是不想停止应用程序来进行复制)
我试图通过为我的 mef 加载的程序集创建一个影子复制的应用程序域来做到这一点,如下所示:
[Serializable]
public class Composer:IComposer
{
private readonly string _pluginPath;
public Composer(IConfigurePluginDirectory pluginDirectoryConfig)
{
_pluginPath = pluginDirectoryConfig.Path;
var setup = new AppDomainSetup();
setup.ShadowCopyFiles = "true"; // really??? is bool not good enough for you?
var appDomain = AppDomain.CreateDomain(AppDomain.CurrentDomain.FriendlyName + "_PluginDomain", AppDomain.CurrentDomain.Evidence, setup);
appDomain.DoCallBack(new CrossAppDomainDelegate(DoWorkInShadowCopiedDomain));
}
private void DoWorkInShadowCopiedDomain()
{
// This work will happen in the shadow copied AppDomain.
var catalog = new AggregateCatalog();
var dc = new DirectoryCatalog(_pluginPath);
catalog.Catalogs.Add(dc);
Container = new CompositionContainer(catalog);
}
public CompositionContainer Container { get; private set; }
}
然后通过此类上的 CompositionContainer 访问我的 MEF 组件目录。然而,组合容器似乎只在影子复制域内初始化(这是有道理的),这意味着它在我的应用程序域中为空。我只是想知道是否有更好的方法来执行此操作或通过跨域查询来获取我的 MEF 组件
如果您不想遵循 Dan Bryant 和 zync 的解决方案,您可以创建一个 shell 应用程序,仅在新的
AppDomain
中执行您的应用程序。
一种方法是:
AppDomain
,启用卷影复制,如果需要,还可以指定将启用卷影复制的目录。 AppDomain.ExecuteAssembly
调用您当前的应用程序。如果您有类库而不是应用程序,您可以尝试以下操作:
将以下接口添加到新的类库项目中:
public interface IRemoteLoader
{
void Load();
void Unload();
}
将此接口的实现添加到需要在新 AppDomain 中执行的类库中。在
Load
和 Unload
方法中,您应该添加代码来分别执行初始化和清理。使该类派生自 MarshalByRefObject
。这是 .NET Remoting 在两个 AppDomain 上创建代理对象所必需的。CreateInstanceAndUnwrap
创建步骤 3 中的加载器类的实例。在步骤 4 创建的对象上使用
Load
和 Unload
。如果您不需要细粒度控制,只需启动/停止就足够了。
我知道这是一个老问题,但是在 Microsoft 发布 VS-MEF 后,它让我想起了我几年前创建的完整示例就是这样做的。
https://www.codeproject.com/Articles/633140/MEF-and-AppDomain-Remove-Assemblies-On-The-Fly
只是为了后代而在这里发帖。
这种场景更接近于移动应用中的自动更新功能。本质上,您希望选择新的程序集(如果在应用程序启动/重新启动时可用)。
设计此问题的一种方法可能是拥有一种通信机制,在启动时向您的应用程序发出信号,表明新程序集可用(可能是 version.txt 文件)。如果是,则同一 version.txt 文件可能指向程序集的新位置。是的 - 您最终可能会创建许多子文件夹来指向正确的版本,但这些可以通过另一个进程来清理。
你可以使用像这样的层次结构 -
版本\ - 版本1.0\ - 版本2.0\
这种类型的设计将更接近众所周知的自动更新范例。
您是否可以选择不使用 DirectoryCatalog 并使用 AssemblyCatalog 加载目录中的所有程序集?您甚至可以转到 code plex 并从 DirectoryCatalog 类复制相同的代码,该代码读取目录并加载程序集。
您将失去动态加载它们的能力,但正如您所提到的,这并不是真正的要求。