關於.NET中的控制反轉(二)- 依賴注入之 MEF

1、MEF是什麼html

       Managed Extensibility Framework (MEF) 是用於建立可擴展的輕量級應用程序的庫。 它讓應用程序開發人員得以發現和使用擴展且無需配置。 它還讓擴展開發人員得以輕鬆地封裝代碼並避免脆弱的緊密依賴性。 MEF 讓擴展不只可在應用程序內重複使用,還能夠跨程序重複使用。git

      MEF 經過組合提供了一種隱式發現它們的方法,而不是明確記錄可用組件。 MEF 組件(稱爲一個部件),以聲明方式詳細說明了其依賴項(稱爲導入)及其可提供的功能(稱爲導出)。 當建立一個部分時,MEF 組合引擎利用從其餘部分得到的功能知足其導入須要。github

     一句話,MEF就是面向接口編程的應用,接口定義行爲,它把實例化類放到代碼運行的時候,經過容器參數肯定。編程

2、MEF示例測試

       在咱們國家,無論你在哪一個銀行辦理銀行卡,只要銀行卡有銀聯標識,那麼你就基本能夠在任意一家銀行取錢、存錢。中國銀聯(China UnionPay)成立於2002年3月,是經國務院贊成,中國人民銀行批准設立的中國銀行卡聯合組織,在境內的銀行必須都支持銀聯。也就是說,中國銀聯定義了一些行爲,例如用戶能夠取錢、存錢,任意一家境內銀行都必須支持銀聯定義的行爲。所以,你在任意一家銀行辦理銀行卡後,就能夠在全部的銀行都進行取錢、存錢等及行爲。下面咱們以此爲例,進行一個簡單的例子:spa

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel.Composition;
  4 using System.ComponentModel.Composition.Hosting;
  5 using System.Linq;
  6 using System.Reflection;
  7 using System.Text;
  8 using System.Threading.Tasks;
  9 
 10 namespace MEF1
 11 {
 12     class Operation
 13     {
 14         static void Main(string[] args)
 15         {
 16             BlankOperation("CBC",300,100);
 17             Console.WriteLine("------------------------------");
 18             BlankOperation("BOC",888,666);
 19             Console.ReadKey();
 20         }
 21 
 22         static void BlankOperation(string bankName,int saveMonenyAmout,int withdrawMoneyAmount)
 23         {
 24             var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
 25             CompositionContainer container = new CompositionContainer(catalog);
 26             var dev = container.GetExportedValue<IUnionPay>(bankName);
 27             dev.SaveMoneny(saveMonenyAmout);
 28             dev.WithdrawMoney(withdrawMoneyAmount);
 29         }
 30     }
 31 
 32   
 33     interface IUnionPay
 34     {
 35         /// <summary>
 36         /// 存錢
 37         /// </summary>
 38         /// <param name="amount">存錢金額</param>
 39         void SaveMoneny(int amount);
 40 
 41         /// <summary>
 42         /// 取錢
 43         /// </summary>
 44         /// <param name="amount">取錢金額</param>
 45         void WithdrawMoney(int amount);
 46 
 47     }
 48 
 49     /// <summary>
 50     /// 工商銀行
 51     /// </summary>
 52     [Export("CBC",typeof(IUnionPay))]
 53     class ICBC : IUnionPay
 54     {
 55         public void SaveMoneny(int amount)
 56         {
 57             Console.WriteLine($"把錢存入工商銀行,金額爲:{amount}");
 58         }
 59 
 60         public void WithdrawMoney(int amount)
 61         {
 62             Console.WriteLine($"從工商銀行取錢,金額爲:{amount}");
 63         }
 64     }
 65 
 66     /// <summary>
 67     /// 建設銀行
 68     /// </summary>
 69     [Export("CCB", typeof(IUnionPay))]
 70     class CCB : IUnionPay
 71     {
 72         public void SaveMoneny(int amount)
 73         {
 74             Console.WriteLine($"把錢存入建設銀行,金額爲:{amount}");
 75         }
 76 
 77         public void WithdrawMoney(int amount)
 78         {
 79             Console.WriteLine($"從建設銀行取錢,金額爲:{amount}");
 80         }
 81     }
 82 
 83     /// <summary>
 84     /// 農業銀行
 85     /// </summary>
 86     [Export("ABC", typeof(IUnionPay))]
 87     class ABC : IUnionPay
 88     {
 89         public void SaveMoneny(int amount)
 90         {
 91             Console.WriteLine($"把錢存入建設銀行,金額爲:{amount}");
 92         }
 93 
 94         public void WithdrawMoney(int amount)
 95         {
 96             Console.WriteLine($"從建設銀行取錢,金額爲:{amount}");
 97         }
 98     }
 99 
100     /// <summary>
101     /// 中國銀行
102     /// </summary>
103     [Export("BOC", typeof(IUnionPay))]
104     class BOC : IUnionPay
105     {
106         public void SaveMoneny(int amount)
107         {
108             Console.WriteLine($"把錢存入建設銀行,金額爲:{amount}");
109         }
110 
111         public void WithdrawMoney(int amount)
112         {
113             Console.WriteLine($"從建設銀行取錢,金額爲:{amount}");
114         }
115     }
116 }

代碼運行後,效果以下:code

3、MEF示例改進htm

      那若是咱們再增長一個銀行實現類,例如招商銀行,那麼須要在MEF1解決方案中增長一個 「CMB」類。但若是咱們的程序已經運行了,此時關閉程序,就會影響用戶在四大行也沒法進行取錢和存錢了,那如何在不關閉程序的前提下,還完成招商銀行接入銀聯卡呢?blog

     答案是爲每一個銀行實現類建立一個解決方案,而後編譯成dll文件,這樣咱們在支持招商銀行接入銀聯時,只須要把 「CMB.dll」文件放入對應目錄,就能夠即不關閉主程序,還能夠無縫支持招商銀行接入銀聯,方案目錄以下:接口

      

     咱們把實現銀聯的銀行的解決方案的生成目錄保存在目錄 「..\bin\Debug\bank\」,用於測試的解決方案和銀聯接口的解決方案生成目錄保存在目錄 「..\bin\Debug\」,編譯程序,生成文件以下圖:

      

  而後測試解決方案LOC容器加載的目錄也需修改成bank目錄下:

 1 using ChinaUnionPay;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.ComponentModel.Composition.Hosting;
 5 using System.IO;
 6 using System.Linq;
 7 using System.Reflection;
 8 using System.Text;
 9 using System.Threading.Tasks;
10 
11 namespace BankOperation
12 {
13     class Program
14     {
15         static void Main(string[] args)
16         {
17             while (true)
18             {
19                 Console.Write($"請輸入銀行名稱:");
20                 string name = Console.ReadLine();
21                 BlankOperation(name, 300, 100);
22                 Console.WriteLine("----------------------------------");
23             }
24         }
25 
26         static void BlankOperation(string bankName, int saveMonenyAmout, int withdrawMoneyAmount)
27         {
28             AggregateCatalog catelog = new AggregateCatalog();
29 
30             // 添加部件所在文件目錄
31             string path = $"{Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath)}\\bank\\";
32             catelog.Catalogs.Add(new DirectoryCatalog(path));
33 
34             // 聲明容器
35             CompositionContainer container = new CompositionContainer(catelog);
36             var dev = container.GetExportedValue<IUnionPay>(bankName);
37 
38             // 動做調用
39             dev.SaveMoneny(saveMonenyAmout);
40             dev.WithdrawMoney(withdrawMoneyAmount);
41         }
42     }
43 }

此時運行測試程序,運行效果以下:

 此時,若在程序運行的時候添加招商銀行,咱們需添加招商銀行的解決方案以下,而後編譯生成:

 1 using ChinaUnionPay;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.ComponentModel.Composition;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace CMB
10 {
11     /// <summary>
12     /// 招商銀行
13     /// </summary>
14     [Export("CMB",typeof(IUnionPay))]
15     public class Operation : IUnionPay
16     {
17         public void SaveMoneny(int amount)
18         {
19             Console.WriteLine($"把錢存入招商銀行,金額爲:{amount}");
20         }
21 
22         public void WithdrawMoney(int amount)
23         {
24             Console.WriteLine($"從招商銀行取錢,金額爲:{amount}");
25         }
26     }
27 }

運行效果以下:

咱們發現,使用MEF模式能夠「高內聚,低耦合」,大大下降了代碼的解耦,每次使一個銀行接入銀行的時候,徹底不影響其餘銀行的正常業務操做。

4、示例代碼地址

      代碼地址:https://github.com/Dwayne112401/MEFDemo.git

      控制反轉(一)地址:https://www.cnblogs.com/dongweian/p/12511272.html

相關文章
相關標籤/搜索