程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 基於.NET平台的分層架構實戰(六)—依賴注入機制及IoC的設計

基於.NET平台的分層架構實戰(六)—依賴注入機制及IoC的設計

編輯:關於.NET

我們設計的分層架構,層與層之間應該是松散耦合的。因為是單向單一調用, 所以,這裡的“松散耦合”實際是指上層類不能具體依賴於下層類, 而應該依賴於下層提供的一個接口。這樣,上層類不能直接實例化下層中的類, 而只持有接口,至於接口所指變量最終究竟是哪一個類,則由依賴注入機制決定 。

之所以這樣做,是為了實現層與層之間的“可替換”式設計 ,例如,現在需要換一種方式實現數據訪問層,只要這個實現遵循了前面定義的 數據訪問層接口,業務邏輯層和表示層不需要做任何改動,只需要改一下配置文 件系統即可正常運行。另外,基於這種結構的系統,還可以實現並行開發。即不 同開發人員可以專注於自己的層次,只有接口被定義好了,開發出來的東西就可 以無縫連接。

在J2EE平台上,主要使用Spring框架實現依賴注入。這裡, 我們將自己做一個依賴注入容器。

依賴注入的理論基礎是Abstract Factory設計模式,這裡結合具體實例簡單介紹一下。

上圖以數據訪問層為例,展示了Abstract Factory模式的應用。如圖, 現假設有針對Access和SQLServer兩種數據庫的數據訪問層,它們都實現了數據訪 問層接口。每個數據訪問層有自己的工廠,所有工廠都實現自IDALFactory接口。 而客戶類(這裡就是業務邏輯層類)僅與工廠接口、數據訪問層接口耦合,而與 具體類無關,這樣,只要通過配置文件確定實例化哪個工廠,就可以得到不同的 數據訪問層。

然而,這種設計雖然可行,但是代碼比較冗余,因為這樣需 要為數據訪問層的每一個實現編寫一個工廠,業務邏輯層也一樣。在以前,我們 毫無辦法,但是,.NET平台引入的反射機制,給我們提供了一種解決方案。使用 反射,每個層只需要一個工廠,然後通過從配置文件中讀出程序集的名稱,動態 加載相應類。另外,為了提高依賴注入機制的效率,這裡引入緩存機制。下面來 看具體實現。

配置

首先,需要在Web工程的Web.config文件的 <appSettings>節點下添加如下兩個項:

<add key="DAL" value=""/>

<add key="BLL" value=""/>

這兩個配置選項分別存 儲要應用的數據訪問和也業務邏輯層的程序集名稱。value目前是空,是因為目前 還沒有各個層次的具體實現。

實現緩存操作輔助類

為實現緩存操 作,我們將緩存操作封裝成一個輔助類,放在Utility工程下,具體代碼如下:

CacheAccess.cs:

CacheAccess

1using System;
2using System.Web;
3using System.Web.Caching;
4
5namespace NGuestBook.Utility
6{
7  /**//// <summary>
8  /// 輔助類,用於緩存操作
9  /// </summary>
10  public sealed class CacheAccess
11   {
12    /**//// <summary>
13    /// 將對象加入 到緩存中
14    /// </summary>
15    /// <param name="cacheKey">緩存鍵</param>
16     /// <param name="cacheObject">緩存對象 </param>
17    /// <param name="dependency">緩存依賴項</param>
18     public static void SaveToCache(string cacheKey, object cacheObject, CacheDependency dependency)
19    {
20      Cache cache = HttpRuntime.Cache;
21      cache.Insert(cacheKey, cacheObject, dependency);
22    }
23
24     /**//// <summary>
25    /// 從緩存中取得對象,不存在則 返回null
26    /// </summary>
27    /// <param name="cacheKey">緩存鍵</param>
28     /// <returns>獲取的緩存對象</returns>
29     public static object GetFromCache(string cacheKey)
30    {
31      Cache cache = HttpRuntime.Cache;
32
33       return cache[cacheKey];
34    }
35  }
36}

封裝依賴注入代碼

因為很多依賴注入代碼非常相似,為了 減少重復性代碼,我們將可復用的代碼先封裝在一個類中。具體代碼如下(這個 類放在Factory工程下):

DependencyInjector.cs:

DependencyInjector

1usi ng System;
2using System.Configuration;
3using System.Reflection;
4using System.Web;
5using System.Web.Caching;
6using NGuestBook.Utility;
7
8namespace NGuestBook.Factory
9{
10  /**//// <summary>
11  /// 依賴注入提供者
12  /// 使用反射機 制實現
13  /// </summary>
14  public sealed class DependencyInjector
15  {
16    /**//// <summary>
17    /// 取得數據訪問層對象
18     /// 首先檢查緩存中是否存在,如果不存在,則利用反射機制返回對象
19    /// </summary>
20    /// <param name="className">數據訪問類名稱</param>
21     /// <returns>數據訪問層對象</returns>
22     public static object GetDALObject(string className)
23    {
24      /**//// <summary>
25      /// 取得數據 訪問層名稱,首先檢查緩存,不存在則到配置文件中讀取
26       /// 緩存依賴項為Web.Config文件
27      /// </summary>
28      object dal = CacheAccess.GetFromCache("DAL");
29      if (dal == null)
30      {
31        CacheDependency fileDependency = new CacheDependency (HttpContext.Current.Server.MapPath("Web.Config"));
32         dal = ConfigurationManager.AppSettings ["DAL"];
33        CacheAccess.SaveToCache ("DAL", dal, fileDependency);
34      }
35
36      /**//// <summary>
37      /// 取得數據 訪問層對象
38      /// </summary>
39       string dalName = (string)dal;
40      string fullClassName = dalName + "." + className;
41      object dalObject = CacheAccess.GetFromCache(className);
42      if (dalObject == null)
43      {
44         CacheDependency fileDependency = new CacheDependency (HttpContext.Current.Server.MapPath("Web.Config"));
45         dalObject = Assembly.Load(dalName).CreateInstance (fullClassName);
46        CacheAccess.SaveToCache (className, dalObject, fileDependency);
47      }
48
49      return dalObject;
50    }
51
52     /**//// <summary>
53    /// 取得業務邏輯層對象
54    /// 首先檢查緩存中是否存在,如果不存在,則利用反射機制返回 對象
55    /// </summary>
56    /// <param name="className">業務邏輯類名稱</param>
57     /// <returns>業務邏輯層對象</returns>
58     public static object GetBLLObject(string className)
59    {
60      /**//// <summary>
61      /// 取得業務 邏輯層名稱,首先檢查緩存,不存在則到配置文件中讀取
62       /// 緩存依賴項為Web.Config文件
63      /// </summary>
64      object bll = CacheAccess.GetFromCache("BLL");
65      if (bll == null)
66      {
67        CacheDependency fileDependency = new CacheDependency (HttpContext.Current.Server.MapPath("Web.Config"));
68         bll = ConfigurationManager.AppSettings ["BLL"];
69        CacheAccess.SaveToCache ("BLL", bll, fileDependency);
70      }
71
72      /**//// <summary>
73      /// 取得業務 邏輯層對象
74      /// </summary>
75       string bllName = (string)bll;
76      string fullClassName = bllName + "." + className;
77      object bllObject = CacheAccess.GetFromCache(className);
78      if (bllObject == null)
79      {
80         CacheDependency fileDependency = new CacheDependency (HttpContext.Current.Server.MapPath("Web.Config"));
81         bllObject = Assembly.Load(bllName).CreateInstance (fullClassName);
82        CacheAccess.SaveToCache (className, bllObject, fileDependency);
83      }
84
85      return bllObject;
86    }
87  }
88}

實現工廠

下面使用兩個輔助類,實現數據訪問層工 廠和業務邏輯層工廠。

DALFactory.cs

DALFactory

1using System;
2using NGuestBook.IDAL;
3
4namespace NGuestBook.Factory
5{
6  /**//// <summary>
7  /// 數據訪問層工廠,用 於獲取相應的數據訪問層對象
8  /// 使用Abstract Factory設計模式 +Facace設計模式+反射機制+緩存機制設計
9  /// </summary>
10  public sealed class DALFactory
11  {
12     /**//// <summary>
13    /// 獲取管理員數據訪問層對象
14    /// </summary>
15    /// <returns> 管理員數據訪問層對象</returns>
16    public static IAdminDAL CreateAdminDAL()
17    {
18      return (IAdminDAL)DependencyInjector.GetDALObject("AdminDAL");
19    }
20
21    /**//// <summary>
22     /// 獲取留言數據訪問層對象
23    /// </summary>
24    /// <returns>留言數據訪問層對象</returns>
25    public static IMessageDAL CreateMessageDAL()
26     {
27      return (IMessageDAL) DependencyInjector.GetDALObject("MessageDAL");
28     }
29
30    /**//// <summary>
31    /// 獲取評論數據訪問層對象
32    /// </summary>
33     /// <returns>評論數據訪問層對象</returns>
34     public static ICommentDAL CreateCommentDAL()
35    {
36       return (ICommentDAL)DependencyInjector.GetDALObject ("CommentDAL");
37    }
38  }
39}

BLLFactory.cs

BLLFactory

1using System;
2using NGuestBook.IBLL;
3
4namespace NGuestBook.Factory
5{
6  /**//// <summary>
7   /// 業務邏輯層工廠,用於獲取相應的業務邏輯層對象
8  /// 使用 Abstract Factory設計模式+Facace設計模式+反射機制+緩存機制設計
9   /// </summary>
10  public sealed class BLLFactory
11  {
12    /**//// <summary>
13    /// 獲 取管理員業務邏輯層對象
14    /// </summary>
15     /// <returns>管理員業務邏輯層對象</returns>
16     public static IAdminBLL CreateAdminBLL()
17    {
18       return (IAdminBLL)DependencyInjector.GetBLLObject ("AdminBLL");
19    }
20
21    /**//// <summary>
22    /// 獲取留言業務邏輯層對象
23     /// </summary>
24    /// <returns>留言業務邏輯層 對象</returns>
25    public static IMessageBLL CreateMessageBLL()
26    {
27      return (IMessageBLL)DependencyInjector.GetBLLObject ("MessageBLL");
28    }
29
30     /**//// <summary>
31    /// 獲取評論業務邏輯層對象
32    /// </summary>
33    /// <returns>評論 業務邏輯層對象</returns>
34    public static ICommentBLL CreateCommentBLL()
35    {
36      return (ICommentBLL)DependencyInjector.GetBLLObject ("CommentBLL");
37    }
38  }
39}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved