1

我有以下情况。在装配 AI 中有以下内容:

public class Service : IService
{
   private readonly IDependency dependency;

   public Service(IDependency dependency)
   {
       this.dependency = dependency;
   }
}

在程序集中 B 和 CI 有不同的实现IDependency

[Export(typeof(IDependency)]
public class Dependency1 : IDependency { }

[Export(typeof(IDependency)]
public class Dependency2 : IDependency { }

如何指示 MEFService为每个导出的实例创建一个实例IDependencies

4

2 回答 2

2

MEF 不支持开箱即用。你有两个选择:

  1. 大概您计划在[ImportMany(typeof(IService))]某个地方导入所有服务实例。相反,您可以导入这样ServiceProvider实现的对象:

    [Export]
    public class ServiceProvider
    {
        [ImportMany]
        public IEnumerable<IDependency> Dependencies { get; set; }
    
        public IEnumerable<IService> GetServices()
        {
           return Dependencies.Select(x => new Service(x));
        }
    }
    
  2. 您可以使用自己的导出提供程序实现来扩充 MEF。我玩弄了添加[ExportMany]这样一个自定义导出提供程序可以识别的属性的想法。它似乎有效,但它只是一个概念证明。请参阅https://bitbucket.org/wcoenen/mefexportmany/

于 2012-04-15T19:50:24.993 回答
1

正如 Wim 所说,这并不是开箱即用的原生支持。如果您希望能够执行以下操作:

[ImportMany]
public IEnumerable<Service> _services { get; set; }

...不使用工厂(如ServiceProviderWim 详述的),则出口提供者将起作用,例如:

public class ServiceExportProvider : ExportProvider
{
  private const string ContractName = AttributedModelServices.GetContractName(typeof(Service));

  public ExportProvider SourceProvider { get; set; }

  protected override IEnumerable<Export> GetExportsCore(ImportDefinition def, AtomicComposition ac)
  {
    if (SourceProvider == null)
      throw new InvalidOperationException("SourceProvider property must be set.");

    if (def.ContractName.Equals(ContractName))
    {
      return SourceProvider
        .GetExports<IDependency>()
        .Select(e => new Export(def.ContractName, () => new Service(e.Value)));
    }

    return Enumerable.Empty<Export>();
  }
}

您不需要[Export]您的Service类型(实际上这可能会导致问题),但如果您已使用容器向提供者注册并设置[Import]属性,则可以[ImportMany]使用实例:ServiceSourceProvider

var catalog = // create catalogs/
var provider = new ServiceExportProvider();
var container = new CompositionContainer(catalog, provider);
provider.SourceProvider = container;
于 2012-04-16T08:59:46.637 回答