2012-03-02 100 views
3

如何覆蓋MEF組合,以便如果導入構造函數要求單個依賴項,並且此需要的依賴項有多個實現,則需要具有最高優先級(元數據)的實現(導出)?覆蓋MEF組合

[Export(typeof(IService))] 
[ExportMetadata("Priority", 1)] 
public class Service1 : IService 
{ 
} 

[Export(typeof(IService))] 
[ExportMetadata("Priority", 2)] 
public class Service2 : IService 
{ 
} 

public interface IService 
{ 
} 

public class ServiceWithDependencies 
{ 
    [ImportingConstructor] 
    public ServiceWithDependencies(IService service) 
    { 

    } 
} 

ServiceWithDependencies通常不會滿足,因爲有IService的多於一個的實現。但我想修改MEF(覆蓋/攔截某些內容),以便它使用優先級元數據並將具有最高優先級的實現注入到ServiceWithDependencies構造函數中。

編輯1

我不想MEF支配我做事的方式。我希望它儘可能隱身。此外,這是一個框架,我不能控制人們如何需要依賴關係。我需要支持基本的構造函數注入。我知道[ImportMany],但這個問題恰恰是關於構造函數注入的。

回答

2

而不是把重點中繼資料的部分,你也可以把它們放在不同的目錄,然後prioritize the catalogs

在我們的應用中,我們利用這個最優先零件在plugins文件夾,然後在應用程序EXE的部分,最後所有的其他庫。

編輯:這是一個完整的示例。

一,類型:

[Export(typeof(IService))] 
public class Service1 : IService { } 

[Export(typeof(IService))] 
public class Service2 : IService { } 

public interface IService { } 

[Export] 
public class ServiceWithDependency 
{ 
    [ImportingConstructor] 
    public ServiceWithDependency(IService service) 
    { 
    } 
} 

[Export] 
public class ServiceWithMultipleDependencies 
{ 
    [ImportingConstructor] 
    public ServiceWithMultipleDependencies(
     [ImportMany] IEnumerable<IService> services) 
    { 
    } 
} 

這裏是你如何設置容器:

var priorityCatalog = new TypeCatalog(typeof(Service1)); 
var priorityProvider = new CatalogExportProvider(priorityCatalog); 

var mainCatalog = new TypeCatalog(
    typeof(ServiceWithDependencies), 
    typeof(ServiceWithMultipleDependencies), 
    typeof(Service2)); 
var mainProvider = new CatalogExportProvider(mainCatalog); 

// priorityProvider gets priority because it is first 
var container = new CompositionContainer(
    priorityProvider, mainProvider); 
priorityProvider.SourceProvider = container; 
mainProvider.SourceProvider = container; 

// will get constructed with Service1 
var foo = container.GetExportedValue<ServiceWithDependency>(); 

// will get constructed with both, proving that both are available 
var bar = container.GetExportedValue<ServiceWithMultipleDependencies>(); 
+0

對不起,如果我很慢,但我不明白這可以幫助構造函數注入。 – W3Max 2012-03-02 14:31:59

+0

與構造函數注入沒有衝突,我們也使用它。 – 2012-03-02 15:15:09

+0

我沒有說有問題,我只是說我不明白它是如何工作的。對不起,但我是MEF世界的新手。你能解釋一下上面的例子嗎? – W3Max 2012-03-02 15:57:46

1

簡單的方法是[ImportMany]並讓chosse擁有最高的元數據。 < - 這就是我們在我們的項目中所做的。

有關可以執行的操作的更多信息 - 您會發現here

public class ServiceWithDependencies 
{ 
    [ImportingConstructor] 
    public ServiceWithDependencies([ImportManyAttribute]IEnumerable<Lazy<IService, IServiceMetadata>> services) 
    { 
     this._TheServiceIWant = services.Max(x=>x.Metadata.Prio).First().Instance; 
    } 
} 

PS:代碼是手寫的,所以LINQ是不對的 - 也許

編輯:

,而不是處理你們班的服務直接也可以導入和工廠至極有一些方法像:

MyPluginFac.GiveServiceWithHighestPrio(); 
MyPluginFac.GiveServiceWithPrio(1); 
... 

public class ServiceWithDependencies 
{ 
    [ImportingConstructor] 
    public ServiceWithDependencies(IServiceFac serviceFac) 
    { 
     this._TheServiceIWant = serviceFac.GiveServiceWithHighestPrio(); 
    } 
} 
+0

恕我直言,這實在是太多了儀式。我不希望MEF決定我做事的方式。我希望它儘可能隱身。此外,這是一個框架,我不能控制人們如何需要依賴關係。我需要支持基本的構造函數注入。我知道[ImportMany],但這個問題恰恰是關於構造函數注入的。 – W3Max 2012-03-02 14:18:49

+0

工廠解決方案的好處是,你有一個容器,你可以從中得到你想要的東西。 – blindmeis 2012-03-06 06:19:57

+0

但你是對的,而不是IService,你必須導入IServiceFac – blindmeis 2012-03-06 10:32:55