2012-02-02 40 views
1

考慮使用MEF創建類型Importer的對象的以下代碼示例,該對象導入ImporterExporter類型的對象,該對象又導入Exporter類型的對象,即Importer -> ImporterExporter -> Exporter。該目錄由CompositionUtility(在本例中明顯簡化)管理。如何處理MEF中的遞歸組合?

我知道MEF將在導入的零件上遞歸解析導入。但是,因爲我想要選擇獨立實例化這些類中的每個類,所以每個具有導入的類都在其構造函數中自行組合以解決這些導入。

using System; 
using System.ComponentModel.Composition; 
using System.ComponentModel.Composition.Hosting; 
using System.Reflection; 

namespace MefRecursionSample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // var importerExporter = new ImporterExporter(); // include this and composition will work 
      var importer = new Importer(); 
      Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7 
      Console.ReadKey(); 
     } 
    } 

    class CompositionUtility 
    { 
     static CompositionUtility() 
     { 
      var executingAssembly = Assembly.GetExecutingAssembly(); 
      var assemblyCatalog = new AssemblyCatalog(executingAssembly); 
      _compositionContainer = new CompositionContainer(assemblyCatalog); 
     } 

     private static CompositionContainer _compositionContainer; 
     private static bool _isComposing; 

     public static void Compose(object part) 
     { 
      _compositionContainer.ComposeParts(part); 
     } 
    } 

    class Importer 
    { 
     public Importer() 
     { 
      CompositionUtility.Compose(this); 
     } 

     [Import] 
     public ImporterExporter ImporterExporter { get; set; } 
    } 

    [Export] 
    class ImporterExporter 
    { 
     public ImporterExporter() 
     { 
      CompositionUtility.Compose(this); 
     } 

     [Import] 
     public Exporter Exporter { get; set; } 
    } 

    [Export] 
    class Exporter 
    { 
     public int Value { get { return 7; } } 
    } 

} 

運行代碼是通往一個組成錯誤「型MefRecursionSample.Importer的ComposablePart」不能重構......」,顯然是因爲我想顯式地構成的東西,MEF也想撰寫。

令我感到驚訝的是,當我包含Main方法的第一行,即創建一個沒有MEF的ImporterExporter類型的對象時,這個「雙重組合」不再引起異常。這是爲什麼?

另外,我怎麼能使它工作,使我可以實例化這些獨立的每一個,但也使他們組成自己鏈時,如在示例中。我想我會在CompositionUtility上引入一個布爾標誌_compositionInProgress,並立即從Compose()返回,當標誌設置爲避免遞歸組合時。有沒有更好的辦法?

回答

2

我認爲在CompositionUtilityCompose方法設置不起作用,因爲可以有地方自動進口串被中斷情況下的標誌。例如,在問題的例子中,如果Exporter使用new在其構造函數中實例化了一個類,並且此類想要自行組合。在原來的解決方案下,該班'呼叫Ccompose將立即返回,從而使班級分解。

因爲我想要類組合自己(從而使其用戶不需要知道MEF),唯一的解決方案是確定具有[Export]屬性的類不得調用Compose(this)的規則。因爲它們將在導入時由MEF自動組成,這會導致「雙重組合」,從而引發異常。

如果需要標記爲[Export]的類必須通過new獨立實例化,而不是通過MEF導入,它們必須具有帶布爾標誌的附加構造函數,該類型構造函數在設置該類的觸發器組合時很好。然而,默認行爲必須是沒有組成以避免上述「雙重組合」。

0

爲什麼不簡單地這樣做?

class Program 
{ 
    private static CompositionContainer _compositionContainer; 

    static void Main(string[] args) 
    { 
     //compose the container just one time in your app 
     var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); 
     _compositionContainer = new CompositionContainer(assemblyCatalog); 

     var importer = _compositionContainer.GetExportedValue<Importer>(); 

     Console.Write(importer.ImporterExporter.Exporter.Value); // should print 7 
     Console.ReadKey(); 
    } 
} 

[Export] 
class Importer 
{ 
    [ImportingConstructor] 
    public Importer(ImporterExporter imex) 
    { 
     this.ImporterExporter = imex; 
    } 

    public ImporterExporter ImporterExporter { get; private set; } 
} 

[Export] 
class ImporterExporter 
{ 
    [ImportingConstructor] 
    public ImporterExporter(Exporter exporter) 
    { 
     this.Exporter = exporter; 
    } 

    public Exporter Exporter { get; private set; } 
} 

[Export] 
class Exporter 
{ 
    public int Value { get { return 7; } } 
} 
+0

我真的很想在它的構造器中編寫一個對象(除非已經在構圖中),所以類的用戶不必擔心MEF的構成,並且可以像使用其他類一樣使用該類。此外,這將有可能將構圖引入到現有的類中。 – PersonalNexus 2012-02-06 19:40:33

0

你真正想做什麼(我認爲)是在對象上調用container.SatisfyImportsOnce()而不是ComposeParts。

ComposeParts將所有導出樹添加到目錄,而SatisfyImportsOnce每個對象都是自己的,組成部分和它,它沒有註冊遞歸導出,所以你可以調用構造函數或使用導入構造函數,你可以同時擁有這兩個。

James。