學習MEF系列(3):導入(Import)和導出(Export) (續)

前言:在上一篇中,我們簡單的介紹了導入和導出的基本知識以及一些基本用法,本篇將介紹一下在導出中經常使用的到兩種技巧(其實就是MEF提供的兩種特性):元數據(Metadata)和自定義導出(Custom Export)

元數據

   在MEF中,導出可提供自身的一些附加信息,我們稱之爲“元數據”。可通過元數據將導出的一些信息、屬性傳遞給導入。上一篇介紹導入的時候提到了ImportMany,在ImportMany的時候有時候可能需要根據特定的條件過濾一些匹配的導出,這時我們可以利用導出的元數據作依據。此外,由於導入部件可以使用元數據來決定要使用哪些導出,或收集有關導出的信息而不必構造導出。 因此,導入必須爲延遲導入才能使用元數據。

  使用元數據需要定義一個稱爲“元數據視圖”的接口,元數據視圖中有且只能定義只讀的屬性,可以使用特性

[DefaultValue]給屬性默認值,元數據視圖中定義的所有屬性在使用時都必須賦值,否則使用改元數據的導出將與任何導入匹配失敗,當然我們也可以使用[DefaultValue]設置默認值,這樣被[DefaultValue]修飾的屬性便可以認爲是可選屬性了。例:

public interface ILogMetadata
{  
     [DefaultValue("FileLog")] 
     string LogType{ get; }

     string Name{ get; }
}

使用元數據視圖修飾的導出:

[Export(typeof(ILog))]
[ExportMetadata("Name", "FileLog")]
[ExportMetadata("LogType", "FileLog")]
public class FileLog: ILog
{
}

注意:特性ExportMetadata的參數第一個爲屬性名稱,第二個是屬性的值。組合容器在組合時部件時會自動匹配所有的元數據視圖,如果有符合的元數據視圖則該導出部件視爲匹配成功。

匹配導入(匹配含有元數據修飾的導出,導入需要使用延時加載):

public class MyLog
{
    [Import]
    public Lazy<ILog, ILogMetadata> singleLog   { get; set; }

   [ImportMany]
    public IEnumerable<Lazy<ILog, ILogMetadata>> logs;
}

自定義導出

  在上面的示例中我們可能會想,當元數據視圖的的必選屬性有很多時,我們是不是得使用很多的[ExportMetadata]來修飾導出,另外元數據視圖的寫法也很容易出錯,其實MEF中可以對Export 和 InheritedExport 進行擴展,用於將元數據封裝到自定義特性中。

  自定義特性可以指定ContractType、ContractName或任何其他元數據。 爲了定義自定義特性,必須使用 MetadataAttribute 特性來修飾繼承自 ExportAttribute(或 InheritedExportAttribute)的類。 例:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]//指定特性的作用域
public class FileLogExportAttribute : ExportAttribute
{
    public FileLogExportAttribute(string logType) 
        : base(typeof(ILog))
    {
        LogType= logType;
        Name = "FileLog";
    }

    public string LogType{ get; private set; }

    public string Name{ get; private set; }
}

使用自定義導出修飾前面導出:

[FileLogExport("FileLog"))
public class FileLog: ILog
{
}

使用自定義導出的特性,ContractType是隱式定義的,

  “在必須將大量的相同元數據(例如,作者或版權信息)應用於多個部件的情況下,使用自定義特性可以節約大量的時間和重複工作。 此外,可以創建自定義特性的繼承樹來爲變體留出餘地。

  若要在自定義特性中創建可選元數據,您可以使用 DefaultValue 特性。 如果此特性應用於自定義特性類中的屬性,它將指定修飾的屬性是可選的,並且不必由導出程序提供。 如果未提供屬性的值,則將爲屬性分配其屬性類型的默認值(通常爲 null、false 或 0。)”——MSDN

結束語:MEF中導入是不能進行自定義的,但MEF中得導出和元數據的配合使得導出更加靈活。

    本文主要參考:http://msdn.microsoft.com/zh-cn/library/ee155691.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章