1. 程式人生 > >c# MEF框架(四 MEF高階進階)

c# MEF框架(四 MEF高階進階)

轉自:http://www.cnblogs.com/yunfeifei/p/3991330.html

好久沒有寫部落格了,今天抽空繼續寫MEF系列的文章。有園友提出這種系列的文章要做個目錄,看起來方便,所以就抽空做了一個,放到每篇文章的最後。

前面四篇講了MEF的基礎知識,學完了前四篇,MEF中比較常用的基本已經講完了,相信大家已經能看出MEF所帶來的便利了。今天就介紹一些MEF中一些較為不常用的東西,也就是大家口中的所謂的比較高階的用法。

前面講的匯出都是在每個類上面新增Export註解,實現匯出的,那麼有沒有一種比較簡便的方法呢?答案是有的,就是在介面上面寫註解,這樣只要實現了這個介面的類都會匯出,而不需要在每個類上面都寫註解。下面僅貼出介面和一個實現類的原始碼,其餘的模仿即可:

介面程式碼如下:

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;

namespace BankInterface
{
   [InheritedExport]
   public interface ICard
   {
      //賬戶金額
      double Money { get; set; }
      //獲取賬戶資訊
      string GetCountInfo();
      
//存錢 void SaveMoney(double money); //取錢 void CheckOutMoney(double money); } }
複製程式碼

介面上面添加了[InheritedExport]標記,沒錯,這個就是用在介面上面的註解。

下面給出一個實現類的程式碼:

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BankInterface;
using System.ComponentModel.Composition;

namespace BankOfChina { //[Export(typeof(ICard))] public class ZHCard : ICard { public string GetCountInfo() { return "Bank Of China"; } public void SaveMoney(double money) { this.Money += money; } public void CheckOutMoney(double money) { this.Money -= money; } public double Money { get; set; } } }
複製程式碼

可以看到,我註釋掉了匯出的註解,執行後,依然可以看到,此類還是被匯出了,執行結果相信看過上一篇的都已經知道了。

注意:這種方法雖然比較簡單,但是隻適用於比較簡單的應用,看完下面後,相信大家會意識到他的不足。

下面進入今天的重點:

 MEF中如何訪問某個具體的物件                                                                      

  前面我們講過在匯出的時候,可以在[Export()]註解中加入名稱標識,從而識別某個具體的物件,然而這種方法只是用於頁面初始化的時候就行過濾,頁面開啟後沒有匯入的就再也匯入不了了,就是說我們不能在匯入的集合中分辨各自的不同,所有匯入的類都是沒有標識的。

  為了給每一個類新增標識,我們要繼承ExportAttribute類,為他新增標識屬性MetaData,首先來寫繼承自ExportAttribute的類,程式碼如下:

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;

namespace BankInterface
{
   /// <summary>
   /// AllowMultiple = false,代表一個類不允許多次使用此屬性
   /// </summary>
   [MetadataAttribute]
   [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
   public class ExportCardAttribute : ExportAttribute
   {
      public ExportCardAttribute()
         :base(typeof(ICard))
      {
      }

      public string CardType { get; set; }
   }
}
複製程式碼

程式碼很簡單,呼叫的父類的構造方法,聲明瞭一個屬性CatdType,下面來新增一個介面,直接修改ICard介面檔案,程式碼如下:

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;

namespace BankInterface
{
   public interface ICard
   {
      //賬戶金額
      double Money { get; set; }
      //獲取賬戶資訊
      string GetCountInfo();
      //存錢
      void SaveMoney(double money);
      //取錢
      void CheckOutMoney(double money);
   }

   public interface IMetaData
   {
      string CardType { get;}
   }
}
複製程式碼

又添加了介面IMetaData,只有一個屬性,注意這個屬性要和剛寫的ExportCardAttribute類中的屬性名稱要一致,這樣才能實現匯出。

下面利用我們的ExportCardAttribute屬性來標記我們要匯出的類:

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BankInterface;
using System.ComponentModel.Composition;

namespace BankOfChina
{
   [ExportCardAttribute(CardType="BankOfChina")]
   public class ZHCard : ICard
   {
      public string GetCountInfo()
      {
         return "Bank Of China";
      }

      public void SaveMoney(double money)
      {
         this.Money += money;
      }

      public void CheckOutMoney(double money)
      {
         this.Money -= money;
      }

      public double Money { get; set; }
   }
}
複製程式碼

在這裡,我們可以設定CardType的屬性,可以根據具體情況使用不同的資料型別。

現在,我們修改主程式的程式碼為:

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using BankInterface;

namespace MEFDemo
{
   class Program
   {
      //其中AllowRecomposition=true引數就表示執行在有新的部件被裝配成功後進行部件集的重組.
      [ImportMany(AllowRecomposition = true)]
      public IEnumerable<Lazy<ICard,IMetaData>> cards { get; set; }

      static void Main(string[] args)
      {
         Program pro = new Program();
         pro.Compose();
         foreach (var c in pro.cards)
         {
            if (c.Metadata.CardType == "BankOfChina")
            {
               Console.WriteLine("Here is a card of Bank Of China ");
               Console.WriteLine(c.Value.GetCountInfo());
            }
            if (c.Metadata.CardType == "NongHang")
            {
               Console.WriteLine("Here is a card of Nong Ye Yin Hang ");
               Console.WriteLine(c.Value.GetCountInfo());
            }
         }
         Console.Read();
      }

      private void Compose()
      {
         var catalog = new DirectoryCatalog("Cards");
         var container = new CompositionContainer(catalog);
         container.ComposeParts(this);
      }
   }
}
複製程式碼

這裡我用到了Lazy延遲載入機制(具體參見Lazy延遲載入),可以看到我們可以根據MetaData的屬性訪問到CardType屬性,從而判斷出Card的型別,從而區分匯入的型別。

相關推薦

c# MEF框架 MEF高階

轉自:http://www.cnblogs.com/yunfeifei/p/3991330.html 好久沒有寫部落格了,今天抽空繼續寫MEF系列的文章。有園友提出這種系列的文章要做個目錄,看起來方便,所以就抽空做了一個,放到每篇文章的最後。 前面四篇講了MEF的基礎

c# MEF框架 見證奇蹟的時刻之實戰應用

轉自 http://www.cnblogs.com/yunfeifei/p/3940075.html 前面三篇講了MEF的基礎和基本到匯入匯出方法,下面就是見證MEF真正魅力所在的時刻。如果沒有看過前面的文章,請到我的部落格首頁檢視。   前面我們都是在一個專案中寫

小白學習之路,基礎函數的

strong 部分 iter 讀者 結果 http 內部 mod 取數 一,內置函數 前面已經認識了函數,對函數都有所了解了,其實呢,在Python中提供了很多內置的函數方便給我們調用。下面會給大家提到一些常用的常用內置函數的用法,當然還有一些其他沒講到的,你也可以看參考文

Chrome開發者工具不完全指南、效能

前言   Profiles面板功能的作用主要是監控網頁中各種方法執行時間和記憶體的變化,簡單來說它就是Timeline的數字化版本。它的功能選項卡不是很多(只有三個),操作起來比較前面的幾塊功能版本來說簡單,但是裡面的資料確很多,很雜,要弄懂它們需要花費一些時間。尤其是在記憶體快照中的各種龐雜的資料。在這篇

階梯博弈演算法詳解尼姆博弈

1.什麼是階梯博弈? 階梯的序號如圖所示,地面表示第0號階梯。每次都可以將一個階梯上的石子向其左側移動任意個石子,沒有可以移動的空間時(及所有石子都位於地面時)輸。 2.階梯博弈的演算法 階梯博弈等效

Aria2 使用手劄簡易部署 + 快速

-a lis evel name trunc miss 放下 hide token  沒錯,又是受夠了迅雷、旋風的各種奇葩減速(哥哥我還買了了VIP!),IDM 對協議支持又太少還有事沒事提示你不是正版三天兩頭鬧著要更新。於是我想起來之前看到過的 Aria2,雖然之前也只是

Java框架學習_SpringSpring_AOP相關術語、AOP_xml的配置和簡單測試涉及junit和aop整合

面向切面程式設計的感覺就是:以前程式是由上往下執行的,如果我需要新增一個什麼功能,就需要去改程式碼,但是我用AOP的動態代理,就像膠帶一樣,往上面一貼就行了,不要用的時候再撕下來,是橫向的,後面會有很多膠帶的型別(就是下面的Advice通知),往上貼,往下帖,環繞貼,遇到異常貼等等,就很方便

jdk源碼閱讀筆記之java集合框架LinkedList

ray private array public 源碼閱讀 jdk源碼閱讀 oid color 解釋 關於LinkedList的分析,會從且僅從其添加(add)方法入手。 因為上一篇已經分析過ArrayList,相似的地方就不再敘述,關註點在LinkedList的特點。 屬

MVC框架驅動類 - 工廠模式

同時 exist class ... string obj 所有 獲取對象 ret 將框架中大部分要創建的對象,都經由驅動類創建,獲取,判斷。這樣做有如下好處: 1 統一管理所有創建的類,包括創建前處理與創建後處理 2 單一創建,防止多次創建類 實例: <?php

.NET深入解析LINQ框架:IQueryable、IQueryProvider接口詳解)

統架構 ble 優雅 架構分析 bad 大致 集合類 linq查詢 語言 閱讀目錄: 1.開篇介紹 2.擴展Linq to Object (應用框架具有查詢功能) 2.1.通過添加IEnumerable<T>對象的擴展方法 2.2.通過繼承IEnumerab

Spring框架AOP面向切面編程

維護 ng- mem 需要 函數 cti oop classpath 實現 一.前言 在以前的項目中,很少去關註spring aop的具體實現與理論,只是簡單了解了一下什麽是aop具體怎麽用,看到了一篇博文寫得還不錯,就轉載來學習一下,博文地址:http://w

我為什麽支持高校的業務系統放棄Apache Struts2框架

源代碼 開源軟件 聯網 應急 mvc框架 工具 銀行 url 方法 月初聽聞廣東某高校(中山大學)發布通知:關於停止使用Apache Struts2開發框架的通知 鑒於S2漏洞較多、維護難度較大,為防範控制網絡安全風險,經研究決定,新建信息化項目不得使用S2; 在用S2的

python函數裝飾器

開放 int col wrap 運行 lag 分享 none name 一。開放封閉原則   1.對擴展是開放的     任何一個程序,不可能在設計之初就已經想好了所有的功能並且未來不做任何更新和修改。所以我們必須允許代碼擴展、添加新功能。   2.對修改是封閉的     

C語言學習

vc++ gin margin 結果 com 語言學 http std oid 面試題中二進制轉換問題,將一個二進制數,從某位開始進行,n位轉換,程序如下所示: 1 /***************************************************

C++標準庫之String

條件 val first operator ins iter substr() oid tof String 常見操作 bool empty() const size_type size() const size_type length() const size_type

C++語言學習——類與對象

clas 進行 自身 ngs 符號表 方法 index clu 每一個 C++語言學習(四)——類與對象 一、構造函數(constructor) 1、構造函數簡介 C++語言中,構造函數是與類名相同的特殊成員函數。在類對象創建時,自動調用構造函數,完成類對象的初始化。類對象

pytest框架

down mod test 正在執行 分享 asa Coding his elf 測試用例setup和teardown 代碼示例一 1 # coding=utf-8 2 import pytest 3 4 5 def setup_module():

C#-運算符

style clas 表達式 參與 優先 運算符 alt 異或運算 格式 算術運算符  +:兩個操作數相加,例:2+3得5  -:第一個操作數減去第二個操作數 例:5-3得2  *:兩個操作數相乘,例:2*3得6  /:分子除以分母,例:5/2得2  %:取模運算符,整除後

【我們一起寫框架】MVVM的WPF框架—DataGrid

pri vertical on() public 頁面 alignment predicate block tco 前言 這個框架寫到這裏,應該有很多同學發現,框架很多地方的細節,其實是違背了MVVM的設計邏輯的。 沒錯,它的確是違背了。 但為什麽明知道違背設計邏輯,

C語言推薦書籍從入門到帶你走上大牛之路珍藏版

轉載自某大佬部落格:https://pymlovelyq.github.io/2018/10/10/CC/ 前言:技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好