【问题标题】:How to export a class from an infrastructure library in MEF?如何从 MEF 中的基础结构库中导出类?
【发布时间】:2012-08-13 23:08:08
【问题描述】:

我有一个项目,其中包含两个模块,一个基础架构(Common 库)和Shell

注意Common有一个FooService,这个有一个ExportAttribute

[Export]
public class FooService
{
}

这个应该由Module1Module2 使用,但是如果我有ImportAttribute,它会抛出错误。请注意评论。

[ModuleExport("Module1.ModuleInit", typeof(Module1.ModuleInit))]
public class ModuleInit : IModule
{
    private readonly IRegionManager _regionManager;
    public IServiceLocator _serviceLocator;

    // [Import(AllowRecomposition=true)]
    public FooService _service;

    [ImportingConstructor]
    public ModuleInit(IRegionManager regionManager, IServiceLocator serviceLocator)
    {
        _regionManager = regionManager;
        _serviceLocator = serviceLocator;
    }

    public void Initialize() { }
}

此代码与Module2 相同。

初始化模块“Module2.ModuleInit”时发生异常。 - 异常消息是:组成保持不变。由于以下错误,更改被拒绝: 合成产生了一个单一的合成错误。根本原因是 下面提供。查看 CompositionException.Errors 属性 更详细的信息。

1) 找到多个与约束匹配的导出 '((exportDefinition.ContractName == "Common.FooService") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "Common.FooService".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))'。

导致:无法设置 import 'Module1.ModuleInit._service (ContractName="Common.FooService")' 在“Module1.ModuleInit”部分。 元素:Module1.ModuleInit._service (ContractName="Common.FooService") --> Module1.ModuleInit --> AssemblyCatalog (Assembly="Module1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

为什么我会收到此异常?我只是导出一个对象。我想知道发生了什么以及如何解决它。

请随意下载,这个项目很小。 Download the compact project

【问题讨论】:

  • 找到多个与约束匹配的导出...
  • 我知道,但我不明白为什么 MEF 会导出两个“FooServices”。我的意思是,“FooService”应该是所有模块的同一个实例

标签: c# module export prism mef


【解决方案1】:

这应该只是一个评论,但我还没有足够的代表来做这件事。无论如何,在我看来,这像是一个范围界定问题。我相信 MEF v1 应该自动将导出视为单例,但我认为它在 v2 中被颠倒了 - 不确定您使用的是哪个版本。我最近在使用 Microsoft.Composition(用于 MVC 的 MEF)时遇到了一个问题,并通过使用 HTTP 请求级别范围限定在整个请求的生命周期中获取单个实例来解决它。

[System.Composition.Export(typeof(ICustomDbContext))]
[System.Composition.Shared(Boundaries.HttpRequest)]
public class CustomDbContext : ICustomDbContext { ... }

【讨论】:

    【解决方案2】:

    解决方案:您浏览每个项目除了 Shell 项目,并查看参考资料;执行以下操作:

    • 只需删除 unityextension 引用,因为您使用的是 MEF
    • 将“通用”引用属性“复制本地”设置为 False
    • 将“Microsoft.Practices.Prism”引用属性“复制本地”设置为 False
    • 将“Microsoft.Practices.Prism.MefExtensions”引用属性“复制本地”设置为 False
    • 将“Microsoft.Practices.Prism.ServiceLocation”引用属性“复制本地”设置为 False
    • 将“System.ComponentModel.Composition”引用属性“复制本地”设置为 False

    进入 Bootstrapper 类,添加:

    protected override void ConfigureAggregateCatalog()
            {
                base.ConfigureAggregateCatalog();
    
                // Add this assembly to the catalog.
                this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
    
                // Add the FooService assembly
                this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(FooService).Assembly));
            }
    

    然后取消注释模块中的 [Import(AllowRecomposition)] 和 FooService。

    在运行项目之前,您需要转到 Visual Studio 菜单,选择 Build -> Clean Project。这将删除之前复制本地 true 的所有 dll 文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-20
      • 1970-01-01
      相关资源
      最近更新 更多