【问题标题】:MEF can load an assembly but doesn't load any partsMEF 可以加载程序集,但不加载任何零件
【发布时间】:2012-06-25 21:59:51
【问题描述】:

我正在使用 MvcContrib 的可移植区域和 MEF 构建一个插件框架,以允许将可移植区域添加为插件,而无需重新编译(只需将您的 dll 放在 bin/Modules 文件夹中)或直接引用插件项目。

在开发插件时,我有两个项目的解决方案:MyFramework 和 MyPlugin。一切正常。我有另一个解决方案,其中只有项目 MyFramework,但 MyPlugin.dll 位于 bin/Modules 文件夹中。当我使用

实例化目录时
string Path = HostingEnvironment.MapPath("~/bin");
string ModulesPath = HostingEnvironment.MapPath("~/bin/Modules");
var catalog = new AggregateCatalog(
    new DirectoryCatalog(Path)
    new DirectoryCatalog(ModulesPath)
);

我可以看到 MyPlugin.dll 的程序集已加载,但未找到任何部件。我尝试使用 MEFx 转储组合状态,如 here 所述,如下所示:

string Path = HostingEnvironment.MapPath("~/bin");
string ModulesPath = HostingEnvironment.MapPath("~/bin/Modules");
var binCatalog = new DirectoryCatalog(Path);
var modulesCatalog = new DirectoryCatalog(ModulesPath);
var catalog = new AggregateCatalog(binCatalog, modulesCatalog);

using (var container = new CompositionContainer(modulesCatalog))
{
    var ci = new CompositionInfo(modulesCatalog, container);
    var stringWriter = new StringWriter();

    CompositionInfoTextFormatter.Write(ci, stringWriter);
    string compositionStateString = stringWriter.ToString();
    Console.WriteLine(s);
}

但是 compositionStateString 只是一个空字符串。

我无法理解问题出在哪里。由于 MyFramework 没有直接引用 MyPlugin,所以这两个项目是否编译为同一个解决方案的一部分应该没有关系,对吧?

附加信息: 我在probing path 中有 bin/Modules。

我通过使用自定义导出属性装饰控制器来导出控制器:

[ExportModuleControllerAttribute("NotificationsController")]
public class NotificationsController : BaseController
{
    //...
}

该属性在 MyFramework 中定义如下:

[AttributeUsage(AttributeTargets.Class), MetadataAttribute]
public class ExportModuleControllerAttribute : ExportAttribute, INamedMetadata        
{
    public string[] Dependencies { get; set; }
    public string Name { get; set; }

    public ExportModuleControllerAttribute(string name, params string[] dependencies)
        : base(typeof(IController))
    {
        Dependencies = dependencies;
        Name = name;
    }
}

与 INamedMetadata 接口一样:

public interface INamedMetadata
{
    #region Properties
    string Name { get; }
    #endregion
}

【问题讨论】:

    标签: asp.net asp.net-mvc plugins mef mvccontrib


    【解决方案1】:

    您如何在模块 dll 中导出类(我猜是控制器)等?让我们看看更多的代码。仅仅设置一个目录是不够的,你实际上必须告诉 mef 把东西放进去。

    还可以对 ci.PartDefinitions 进行计数,看看里面是否有任何东西。事实上,在调试器中检查 ci 和容器变量,看看你在其中得到了什么。

    另外你为什么只检查 modulesCatalog 你不应该检查目录例如

     var ci = new CompositionInfo(catalog, container);
    

    无论如何希望这会为您指明正确的方向。

    【讨论】:

    • 我已经编辑了上面的问题以添加导出代码。在我的实际代码中,我正在检查目录,但我认为它会更清楚地表明问题出在 modulesCatalog 上,因为那是没有正确加载 Parts 的目录。如果我检查目录,我会得到与只检查 binCatalog 相同的输出。使用目录创建 CompositionInfo,ci.PartDefinitions.Count() 在应该返回 8 时返回 4。我在调试器中检查了 ci,但我不太确定除了不存在的部件之外我在寻找什么。
    • 尝试将你的模块放在不同的目录中,比如 app_code 也会关闭探测路径的东西。如果您希望导出的元数据 MEf 具有用于此目的的元数据属性,也请尝试使用标准 Exportattribute 而不是自定义导出。
    【解决方案2】:

    @Peter 提出了一些很好的观点。我还建议您尝试 Visual MEFX。你可以在mefcontrib-tools 项目中找到它。这将让您以交互方式探索您的程序集。你可以一次添加一个,看看有没有导出的。

    这是一篇关于如何设置的文章:Getting Started with Visual MEFX

    【讨论】:

    • 我会检查的。谢谢。
    • 当我将 MyPlugin.dll 加载到 Visual MEFX 中时,没有任何反应。我认为这应该意味着该 dll 中没有导出,尽管可以更清楚地说明。也许我导出不正确?
    • 是的,根据我的经验,当程序集没有导出时,Visual MEFX 什么都不做。它会尝试简化您声明出口的方式。首先使用没有元数据的普通导出属性,看看它是否出现。然后尝试添加一些元数据,看看是否可行。希望经过几次迭代后,您可以准确找出问题所在。
    • 我还没有弄清楚这个问题,因为工作优先级让我从事其他项目,但这个答案让我指出了正确的方向。谢谢吉姆。
    【解决方案3】:

    您需要确保已将 *.pdb 文件包含在启动 bin 文件夹中。

    *.dll 不足以满足导入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      相关资源
      最近更新 更多