2010-01-05 185 views
36

我想弄清MEF的構造函數注入屬性。我不知道如何告訴它加載構造函數的參數。MEF構造函數注入

這是我試圖加載

[ImportMany(typeof(BUsers))] 
public IEnumerable<BUsers> LoadBUsers { get; set; } 

這裏是我使用導入組件代碼中的財產。

try 
{ 
    var catalog = new AggregateCatalog(); 
    catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
    catalog.Catalogs.Add(new DirectoryCatalog("DI")); 
    var container = new CompositionContainer(catalog); 
    container.ComposeParts(this); 
} 

這裏是我想要當您使用ImportingConstructor屬性,參數來構造成爲進口加載

[Serializable] 
[Export(typeof(BUsers))] 
public class EditProfile : BUsers 
{ 
    [ImportingConstructor] 
    public EditProfile(string Method, string Version) 
    {    
     Version = "2"; 
     Action = "Edit"; 
     TypeName = "EditProfile"; 
    } 

回答

53

類。默認情況下,您導入的內容(合同名稱)基於您要導入的參數或屬性的類型。因此,在這種情況下,您的導入的合同類型是字符串,並且第一個和第二個參數之間沒有實際差異。

它看起來像你正在嘗試使用導入來提供配置值,這不一定是它的設計目的。爲了得到它做你想要什麼,你應該爲每個參數的重寫合同的名稱,如:

[ImportingConstructor] 
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version) 
{ } 

然後,你需要方法和出口版本在你的容器。這樣做的一種方式就是直接添加:

var container = new CompositionContainer(catalog); 
container.ComposeExportedValue("Method", "MethodValue"); 
container.ComposeExportedValue("Version", "2.0"); 
container.ComposeParts(this); 

(注意ComposeExportedValue實際上是對靜態AttributedModelServices類中定義的擴展方法。)

如果你想從配置讀取這些值可以創建自己的導出提供程序,該提供程序讀取配置並提供其中的值作爲導出到容器。

處理這種情況的另一種方法是隻導入一個接口,該接口通過名稱提供對配置值的訪問,並從構造函數的主體中獲取所需的值。

+0

我剛剛在CodePlex上下載了一個新的。 ComposeExportedValue()的方法不在CompositionContainer的類中。它在哪裏? – 2010-01-20 22:18:51

+0

我想我找到了方法。它屬於AttributedModelServices類,其中方法被定義爲類CompositionContainer的擴展方法。 – 2010-01-20 22:32:20

+1

@ David.Chu.ca是的,ComposeExportedValue是AttributedModelServices類的擴展方法。 – 2010-01-21 18:33:14

23

我喜歡丹尼爾的解決方案;然而,我所看到的只有一件事是參與者名稱(創建CompopositionContrainer())和導出部分與[ImportingConstructor]之間的自定義CTOR緊密耦合。例如,「方法」在兩個地方都有兩個匹配。如果參與者和導出部分處於差異項目中,則難以維護導出部分。

如果可能,我會將第二個CTOR添加到Export部件類。例如:

[Export(typeof(BUsers))] 
public class EditProfile : BUsers 
{ 
    [ImportingConstructor] 
    public EditProfile(EditProfileParameters ctorPars) 
    : this(ctorPars.Method, ctorPars.Version) {} 

    public EditProfile(string Method, string Version) 
    { 
     Version = "2"; 
     Action = "Edit"; 
     TypeName = "EditProfile"; 
    } 

類EditProfileParameters應該是直截了當:方法和版本的兩個屬性:

[Export] 
public class EditProfileParameters{ 
    public string Method { get; set; } 
    public string Version { get; set; } 
} 

關鍵的一點是要導出的屬性添加到類。然後MEF應該能夠將該類映射到EditProfile的CTOR的參數。

下面是例子,導出一部分添加到容器:

var container = new CompositionContainer(catalog); 
var instance1 = new EditProfileParameters(); 
// set property values from config or other resources 
container.ComposeExportedValue(instance1); 
container.ComposeParts(this); 
0

雖然太遲了,這裏是一個利用MEF的鮮爲人知的功能的另一種方法:房產出口

public class ObjectMother 
{ 
    [Export] 
    public static EditProfile DefaultEditProfile 
    { 
     get 
     { 
      var method = ConfigurationManager.AppSettings["method"]; 
      var version = ConfigurationManager.AppSettings["version"]; 

      return new EditProfile(method,version); 
     } 
    } 
} 

ObjectMother不需要使用這些工具,EditProfile也不需要任何屬性。

+0

不錯的功能,但如果'EditProfile'包含任何導入?在這種情況下,您需要在容器上調用「SatisfyImportsOnce」。這很痛。目前我對這個問題沒有真正的解決方案。 – 2015-10-13 14:38:50

+0

在這種情況下,我們正在構建一個手動實例化EditProfile的工廠。如果EditProfile在構造函數中需要額外的依賴關係,則可以通過ImportingConstructor始終將這些依賴關係帶入Factory。我應該指出,如果向EditProfile添加其他依賴項,這是應用程序中此構造函數的唯一引用,並且您將收到編譯時錯誤。這是一個公平交易,恕我直言。 – bryanbcook 2015-10-14 18:00:29