2012-04-15 72 views
1

我有以下情况。在组件A我有以下:使用由MEF组成的参数创建类的实例

public class Service : IService 
{ 
    private readonly IDependency dependency; 

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

在组件B和C I具有IDependency不同的实现:

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

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

如何可以指示MEF为每个出口IDependencies的创建的Service实例?

回答

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/

1

正如Wim所说,这不是开箱即用的本地支持。如果您希望能够做这样的事情:

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

...不使用的工厂(如ServiceProvider由维姆详细说明),然后出口提供一定的作用,如:

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]Service实例[ImportMany]如果你与你的容器提供者登记,并设置SourceProvider属性:

var catalog = // create catalogs/ 
var provider = new ServiceExportProvider(); 
var container = new CompositionContainer(catalog, provider); 
provider.SourceProvider = container;