12

我试图在我的 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 组件

4

3 回答 3

3

如果您不想遵循 Dan Bryant 和 zync 的解决方案,您可以创建一个 shell 应用程序,它只是在新的AppDomain.

一种方法是:

  1. 创建一个新的应用程序项目,它将成为 shell 应用程序。
  2. 在 shell 应用程序中,创建AppDomain,启用卷影复制,如果您愿意,指定将启用卷影复制的目录。
  3. 用于AppDomain.ExecuteAssembly调用您当前的应用程序。

如果您有一个类库而不是应用程序,则可以尝试以下操作:

  1. 创建一个新的类库项目。
  2. 在新建的类库项目中添加如下接口:

    public interface IRemoteLoader  
    {  
        void Load();  
        void Unload();  
    }
    
  3. 将此接口的实现添加到需要在新 AppDomain 中执行的类库中。在LoadUnload方法中,您应该添加代码以分别执行初始化和清理。使类派生自MarshalByRefObject. 这是 .NET Remoting 在两个 AppDomains 上创建代理对象所必需的。

  4. 创建新的 AppDomain 后,使用CreateInstanceAndUnwrap从步骤 3 创建加载程序类的实例。

  5. 在步骤 4 中创建的对象上使用Loadand Unload

如果您不进行细粒度控制并且简单地启动/停止就足够了,这就足够了。

于 2012-10-04T14:19:32.213 回答
-1

这种场景更接近于移动应用中的自动更新功能。本质上,如果在 App Start/Restart 上可用,您希望获取新的程序集。

一种设计方法可能是使用一种通信机制在启动时向您的应用程序发出新程序集可用的信号(可能是 version.txt 文件)。如果是,那么相同的 version.txt 文件可以指向程序集的新位置。是的 - 您最终可能会创建许多子文件夹以指向正确的版本,但这些可以由另一个进程清理。

你可以使用这样的层次结构 -

版本\ - 版本1.0\ - 版本2.0\

这种类型的设计将更接近于众所周知的自动更新范例。

于 2012-10-01T14:11:44.303 回答
-2

您是否可以选择不使用 DirectoryCatalog 并使用 AssemblyCatalog 加载目录中的所有程序集?您甚至可以转到代码 plex 并从 DirectoryCatalog 类中复制相同的代码,该类会读取目录并加载程序集。

您将失去动态加载它们的能力,但正如您所提到的,这并不是真正的要求。

于 2012-09-29T20:16:31.283 回答