MEF程序設計指南五:遲延(Lazy)加載導出部件(Export Part)與元數據(Metadata)

  MEF中使用導出與導入,實質上就是對一個對象的實例化的過程,通過MEF的特性降低了對象的直接依賴,從而讓系統的設計達到一種高靈活、高擴展性的效果。在具體的設計開發中,存在着某些對象是不需要在系統運行或者的附屬對象初始化的時候進行實例化的,僅僅只需要在需要使用到他的時候纔會進行實例化,從系統的上來說這也是提高系統性能的一種可行的實現方式,這種方式就可以理解爲對象的遲延初始化,或者叫遲延加載。MEF也對此使用場景提供了完善的實現機制,下面來看看在MEF中的遲延初始化是如何使用的。

namespace MEFTraining.LzayImports
{
    
public interface ILogger
    {
        
void WriteLog(string message);
    }

    [Export(
typeof(ILogger))]
    
public class DBLogger : ILogger
    {
        
public void WriteLog(string message)
        {
            MessageBox.Show(message);
        }
    }
}

 

  通過使用前幾篇博文中使用的日誌組件爲例,在日誌記錄的具體實現對象上進行對象的導出[Export]配置。如果是使用傳統的方式進行部件的導入則如下代碼塊所示:

[Import(typeof(ILogger))]
public ILogger Logger { getset; }

 

  如果需要進行遲延(Lazy)加載,MEF專門提供了用於遲延加載的方式,既使用Lazy類來完成遲延加載,然後通過其他屬性Value獲取到所加載到的對象。詳細的使用如下代碼塊:

public partial class MainPage : UserControl
{
    
//傳統加載
    [Import(typeof(ILogger))]
    
public ILogger Logger { getset; }
    
    
//遲延加載
    [Import]
    
public Lazy<ILogger> Service;

    
public MainPage()
    {
        InitializeComponent();

        CompositionInitializer.SatisfyImports(
this);

        Logger.WriteLog(
"日誌內容");

        Service.Value.WriteLog(
"日誌內容");
    }
}

 

  通過調試輸出可以得到使用遲延導入的對象的詳細信息,下面是通過在命令窗口中輸出的Service和Service.Value的詳細信息。

Service
ThreadSafetyMode
=PublicationOnly, IsValueCreated=true, IsValueFaulted=false, Value={MEFTraining.LzayImports.DBLogger}
    IsValueCreated: 
true
Service.Value
{MEFTraining.LzayImports.DBLogger}
    [MEFTraining.LzayImports.DBLogger]: {MEFTraining.LzayImports.DBLogger}

 

   遲延加載還支持元數據的導出和導入,主要使用[MetadataAttribute]特性實現,實際開發中可以進行自定義元數據結構,這裏以一個空的元數據接口進行元數據的導入應用演示。

public interface IMetadata
{
      
}

 

  在導出部件中就可以使用元數據特性進行聲明,如下簡單的應用。

[MetadataAttribute]
[Export(
typeof(Users))]
public class Users
{
    
public string UserName = "張三";
}

 

  元數據的導入應用如下代碼塊所示:

public partial class MetadataControl : UserControl
{
    [Import(
typeof(Users))]
    
public Lazy<Users,IMetadata> Users { getset; }

    
public MetadataControl()
    {
        InitializeComponent();

        
//宿主MEF託管擴展容器
        CompositionInitializer.SatisfyImports(this);

        MessageBox.Show(Users.Value.UserName);
    }
}

 

  對於的調試輸出爲下面代碼塊所示:

Users
ThreadSafetyMode
=PublicationOnly, IsValueCreated=true, IsValueFaulted=falseValue={MEFTraining.LzayImports.Users}
    
base {System.Lazy<MEFTraining.LzayImports.Users>}: ThreadSafetyMode=PublicationOnly, IsValueCreated=true, IsValueFaulted=false, Value={MEFTraining.LzayImports.Users}
    Metadata: {_proxy_MEFTraining.LzayImports.IMetadata_0174a468
-9771-4271-a37e-9a4a83eca6bd}

 

  MEF中也提供了專門用於元數據導入、導出的特性[ExportMetadata],使用ExportMetadata基本可以滿足大部分元數據的導出、導入支持。通過修改上面的示例來實現自定義元數據結構的導入、導出應用演示。

public interface IMetadata
{
    
string Name { get; }
}

[ExportMetadata(
"Name","李四")]
[Export(
typeof(Users))]
public class Users
{
    
public string UserName = "張三";
}

 

  上面的示例代碼演示了通過元數據導出屬性名爲“Name”,其值爲“李四”的元數據信息,並且還定義了一個用於承載元數據結構的結構,接下來就可以通過遲延加載導入,進行元數據的獲取了。

public partial class MetadataControl : UserControl
{
    [Import(
typeof(Users))]
    
public Lazy<Users,IMetadata> Users { getset; }

    
public MetadataControl()
    {
        InitializeComponent();

        
//宿主MEF託管擴展容器
        CompositionInitializer.SatisfyImports(this);

        MessageBox.Show(Users.Value.UserName);
    }
}

 

  下圖爲允許調試中的截圖,可以很清楚的看到,在進行遲延導入的時候已經將導出部件中的元數據信息成功的導入到了當前對象實例屬性中。

    

 

  下面是完整的元數據應用實例代碼。

namespace MEFTraining.LzayImports
{
    
public partial class MetadataControl : UserControl
    {
        [Import(
typeof(Users))]
        
public Lazy<Users,IMetadata> Users { getset; }

        
public MetadataControl()
        {
            InitializeComponent();

            
//宿主MEF託管擴展容器
            CompositionInitializer.SatisfyImports(this);

            MessageBox.Show(Users.Value.UserName);
        }
    }

    
public interface IMetadata
    {
        
string Name { get; }
    }

    [ExportMetadata(
"Name","李四")]
    [Export(
typeof(Users))]
    
public class Users
    {
        
public string UserName = "張三";
    }
}

 

   除此之外,遲延加載也是支持弱類型的元數據類型的,也可以對元數據進行過濾,這裏就不做詳細的介紹,有興趣的朋友可以自己去研究研究。

 

  

 

  本篇參考:Lazy Imports  、Exports and Metadata  

  MEF官方網站:http://mef.codeplex.com/

  推薦指南:MEF程序設計指南一:在應用程序中宿主MEF

         MEF程序設計指南二:Silverlight中使用CompositionInitializer宿主MEF

         MEF程序設計指南三:MEF中組合部件(Composable Parts)與契約(Contracts)的基本應用

       MEF程序設計指南四:使用MEF聲明導出(Exports)與導入(Imports)

發佈了110 篇原創文章 · 獲贊 3 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章