【问题标题】:MEF Runtime Plugin Update IssueMEF 运行时插件更新问题
【发布时间】:2013-04-22 15:19:18
【问题描述】:

问题

我的 MEF 代码在运行时未从与 DirectoryCatalog 关联的文件夹中正确更新程序集。插件在运行时成功加载,但是当我更新 dll 并在 DirectoryCatalog 上调用 Refresh 时,程序集没有得到更新。

背景

我正在构建一个具有 MEF 容器的 dll,并使用 DirectoryCatalog 来查找本地插件文件夹。我目前从一个简单的 WinForm 调用此 dll,该 dll 设置为使用单独的项目以使用 ShadowCopy,因此我可以覆盖我的插件文件夹中的 dll。我没有使用 FileWatcher 更新此文件夹,而是公开了一个在 DirectoryCatalog 上调用刷新的公共方法,因此我可以随意更新程序集而不是自动更新程序集。

代码

基类实例化 MEF 目录和容器,并将它们保存为类变量以供以后引用访问

    public class FieldProcessor
{
    private CompositionContainer _container;
    private DirectoryCatalog dirCatalog;

    public FieldProcessor()
    {
        var catalog = new AggregateCatalog();
        //Adds all the parts found in the same assembly as the TestPlugin class
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(TestPlugin).Assembly));
        dirCatalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + "Plugin\\");
        catalog.Catalogs.Add(dirCatalog);

        //Create the CompositionContainer with the parts in the catalog
        _container = new CompositionContainer(catalog);
    }

    public void refreshCatalog()
    {
        dirCatalog.Refresh();
    }

} ...

这是我要覆盖的插件。我的更新测试是返回的字符串输出到文本框,我更改插件返回的字符串,重建,并将其复制到插件文件夹中。但它不会为正在运行的应用程序更新,直到我关闭并重新启动应用程序。

[Export(typeof(IPlugin))]
[ExportMetadata("PluginName", "TestPlugin2")]
public class TestPlugin2 : IPlugin
{
    public IEnumerable<IField> GetFields(ContextObject contextObject, params string[] parameters)
    {
        List<IField> retList = new List<IField>();
        //Do Work Return Wrok Results
        retList.Add(new Field("plugin.TestPlugin2", "TestPluginReturnValue2"));
        return retList;
    }
}

编辑

导入语句
    [ImportMany(AllowRecomposition=true)]
    IEnumerable<Lazy<IPlugin, IPluginData>> plugins;

研究

我已经进行了相当广泛的研究,并且在文章和代码示例中无处不在,答​​案似乎是,将 DirectoryCatalog 添加到容器并保存该目录的引用,然后在该引用上调用 Refresh,之后添加了一个新插件,它将更新程序集......我正在这样做,但它没有显示来自新插件 dll 的更新输出。

请求

有没有人见过这个问题,或者知道是什么原因导致我的程序集在运行时没有更新?任何额外的信息或见解将不胜感激。

解决方案

感谢 Panos 和 Stumpy 提供的链接,这些链接让我找到了解决问题的方法。对于未来的知识寻求者,我的主要问题是 Refresh 方法不会更新程序集,因为新程序集与覆盖的 dll 具有完全相同的程序集名称。对于我的 POC,我刚刚测试了在程序集名称后附加日期的重建,其他一切都相同,它就像一个魅力。他们在下面的 cmets 中的链接非常有用,如果您有同样的问题,建议您使用。

【问题讨论】:

  • DirectoryCatalog.Refresh 不会检测到更新的组件。只有新的或已删除的。查看此答案以获取解决方法和建议:stackoverflow.com/a/14842417/850119
  • 我的 dll 在加载时被锁定,因此我无法用新的 dll 覆盖它们。你没有这个问题吗?你做了什么让它们可以更新的事情吗?
  • 是的,我确实有这个问题。我顺便提到的步骤之一是启用“影子复制”。 Shadow Copy 允许程序提取 dll 程序集的本地副本,并将它们添加到本地缓存,而不是锁定 dll。必须启用此功能以允许您在运行时“热交换”dll,否则您需要停止程序,更改 dll,然后重新启动它。我认为这是我查看的示例,但如果它不适合您使用谷歌 MEF 和 Shadow Copy,stackoverflow.com/questions/12593308/…

标签: c# .net plugins mef updates


【解决方案1】:

您是否将AllowRecomposition 参数设置为您的导入属性?

AllowRecomposition
Gets or sets a value that indicates whether the property or field will be recomposed when exports with a matching contract have changed in the container.

http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importattribute(v=vs.95).aspx

编辑:

DirectoryCatalog 不更新程序集,仅添加或删除: http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.directorycatalog.refresh.aspx

解决方法: https://stackoverflow.com/a/14842417/2215320

【讨论】:

  • 我做了,抱歉我最初没有发布导入语句代码,我已经更新了问题以反映我的导入语句。
  • 和你的刷新代码?我认为问题在内部。你说不使用 FileSystemWatcher,你如何检测和重新加载你的程序集?
  • Refresh 不会更新程序集,而只会添加或删除它们。 msdn.microsoft.com/en-us/library/… 见:stackoverflow.com/a/14842417/2215320
  • 感谢我正在进一步调查的链接,可能需要稍微改变用例,但这些似乎它们将有很大帮助。解决后我会回复并将其标记为答案。再次感谢。
  • 这是程序集命名的问题,一旦我获得使用唯一程序集名称的代码,代码就像冠军一样工作。感谢您的所有帮助。
猜你喜欢
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-05
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多