.NET平台依赖注入机制及IoC的设计与实现
生活随笔
收集整理的這篇文章主要介紹了
.NET平台依赖注入机制及IoC的设计与实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
我們設計的分層架構,層與層之間應該是松散耦合的。因為是單向單一調用,所以,這里的“松散耦合”實際是指上層類不能具體依賴于下層類,而應該依賴于下層提供的一個接口。這樣,上層類不能直接實例化下層中的類,而只持有接口,至于接口所指變量最終究竟是哪一個類,則由依賴注入機制決定。
之所以這樣做,是為了實現層與層之間的“可替換”式設計,例如,現在需要換一種方式實現數據訪問層,只要這個實現遵循了前面定義的數據訪問層接口,業務邏輯層和表示層不需要做任何改動,只需要改一下配置文件系統即可正常運行。另外,基于這種結構的系統,還可以實現并行開發。即不同開發人員可以專注于自己的層次,只有接口被定義好了,開發出來的東西就可以無縫連接。
在J2EE平臺上,主要使用Spring框架實現依賴注入。這里,我們將自己做一個依賴注入容器。
依賴注入的理論基礎是Abstract Factory設計模式,這里結合具體實例簡單介紹一下。
上圖以數據訪問層為例,展示了Abstract Factory模式的應用。如圖,現假設有針對Access和SQLServer兩種數據庫的數據訪問層,它們都實現了數據訪問層接口。每個數據訪問層有自己的工廠,所有工廠都實現自IDALFactory接口。而客戶類(這里就是業務邏輯層類)僅與工廠接口、數據訪問層接口耦合,而與具體類無關,這樣,只要通過配置文件確定實例化哪個工廠,就可以得到不同的數據訪問層。
?
然而,這種設計雖然可行,但是代碼比較冗余,因為這樣需要為數據訪問層的每一個實現編寫一個工廠,業務邏輯層也一樣。在以前,我們毫無辦法,但是,.NET平臺引入的反射機制,給我們提供了一種解決方案。使用反射,每個層只需要一個工廠,然后通過從配置文件中讀出程序集的名稱,動態加載相應類。另外,為了提高依賴注入機制的效率,這里引入緩存機制。下面來看具體實現。
?配置
首先,需要在Web工程的Web.config文件的<appSettings>節點下添加如下兩個項:
<add?key="DAL"?value=""/>
<add?key="BLL"?value=""/>
using?System.Web;
using?System.Web.Caching;
namespace?NGuestBook.Utility
{
????/**//**//**////?<summary>
????///?輔助類,用于緩存操作
????///?</summary>
????public?sealed?class?CacheAccess
????{
????????/**//**//**////?<summary>
????????///?將對象加入到緩存中
????????///?</summary>
????????///?<param?name="cacheKey">緩存鍵</param>
????????///?<param?name="cacheObject">緩存對象</param>
????????///?<param?name="dependency">緩存依賴項</param>
????????public?static?void?SaveToCache(string?cacheKey,?object?cacheObject,?CacheDependency?dependency)
????????{
????????????Cache?cache?=?HttpRuntime.Cache;
????????????cache.Insert(cacheKey,?cacheObject,?dependency);
????????}
????????/**//**//**////?<summary>
????????///?從緩存中取得對象,不存在則返回null
????????///?</summary>
????????///?<param?name="cacheKey">緩存鍵</param>
????????///?<returns>獲取的緩存對象</returns>
????????public?static?object?GetFromCache(string?cacheKey)
????????{
????????????Cache?cache?=?HttpRuntime.Cache;
????????????return?cache[cacheKey];
????????}
????}
}
?
using?System.Configuration;
using?System.Reflection;
using?System.Web;
using?System.Web.Caching;
using?NGuestBook.Utility;
namespace?NGuestBook.Factory
{
????/**//**//**////?<summary>
????///?依賴注入提供者
????///?使用反射機制實現
????///?</summary>
????public?sealed?class?DependencyInjector
????{
????????/**//**//**////?<summary>
????????///?取得數據訪問層對象
????????///?首先檢查緩存中是否存在,如果不存在,則利用反射機制返回對象
????????///?</summary>
????????///?<param?name="className">數據訪問類名稱</param>
????????///?<returns>數據訪問層對象</returns>
????????public?static?object?GetDALObject(string?className)
????????{
????????????/**//**//**////?<summary>
????????????///?取得數據訪問層名稱,首先檢查緩存,不存在則到配置文件中讀取
????????????///?緩存依賴項為Web.Config文件
????????????///?</summary>
????????????object?dal?=?CacheAccess.GetFromCache("DAL");
????????????if?(dal?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????dal?=?ConfigurationManager.AppSettings["DAL"];
????????????????CacheAccess.SaveToCache("DAL",?dal,?fileDependency);
????????????}
????????????/**//**//**////?<summary>
????????????///?取得數據訪問層對象
????????????///?</summary>
????????????string?dalName?=?(string)dal;
????????????string?fullClassName?=?dalName?+?"."?+?className;
????????????object?dalObject?=?CacheAccess.GetFromCache(className);
????????????if?(dalObject?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????dalObject?=?Assembly.Load(dalName).CreateInstance(fullClassName);
????????????????CacheAccess.SaveToCache(className,?dalObject,?fileDependency);
????????????}
????????????return?dalObject;
????????}
????????/**//**//**////?<summary>
????????///?取得業務邏輯層對象
????????///?首先檢查緩存中是否存在,如果不存在,則利用反射機制返回對象
????????///?</summary>
????????///?<param?name="className">業務邏輯類名稱</param>
????????///?<returns>業務邏輯層對象</returns>
????????public?static?object?GetBLLObject(string?className)
????????{
????????????/**//**//**////?<summary>
????????????///?取得業務邏輯層名稱,首先檢查緩存,不存在則到配置文件中讀取
????????????///?緩存依賴項為Web.Config文件
????????????///?</summary>
????????????object?bll?=?CacheAccess.GetFromCache("BLL");
????????????if?(bll?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????bll?=?ConfigurationManager.AppSettings["BLL"];
????????????????CacheAccess.SaveToCache("BLL",?bll,?fileDependency);
????????????}
????????????/**//**//**////?<summary>
????????????///?取得業務邏輯層對象
????????????///?</summary>
????????????string?bllName?=?(string)bll;
????????????string?fullClassName?=?bllName?+?"."?+?className;
????????????object?bllObject?=?CacheAccess.GetFromCache(className);
????????????if?(bllObject?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????bllObject?=?Assembly.Load(bllName).CreateInstance(fullClassName);
????????????????CacheAccess.SaveToCache(className,?bllObject,?fileDependency);
????????????}
????????????return?bllObject;
????????}
????}
}
using?NGuestBook.IDAL;
namespace?NGuestBook.Factory
{
????/**//**//**////?<summary>
????///?數據訪問層工廠,用于獲取相應的數據訪問層對象
????///?使用Abstract?Factory設計模式+Facace設計模式+反射機制+緩存機制設計
????///?</summary>
????public?sealed?class?DALFactory
????{
????????/**//**//**////?<summary>
????????///?獲取管理員數據訪問層對象
????????///?</summary>
????????///?<returns>管理員數據訪問層對象</returns>
????????public?static?IAdminDAL?CreateAdminDAL()???????
?{
????????????return?(IAdminDAL)DependencyInjector.GetDALObject("AdminDAL");
??????}
????????/**//**//**////?<summary>
????????///?獲取留言數據訪問層對象
????????///?</summary>
????????///?<returns>留言數據訪問層對象</returns>
????????public?static?IMessageDAL?CreateMessageDAL()
????????{
????????????return?(IMessageDAL)DependencyInjector.GetDALObject("MessageDAL");
????????}
????????/**//**//**////?<summary>
????????///?獲取評論數據訪問層對象
????????///?</summary>
????????///?<returns>評論數據訪問層對象</returns>
????????public?static?ICommentDAL?CreateCommentDAL()
????????{
????????????return?(ICommentDAL)DependencyInjector.GetDALObject("CommentDAL");
????????}
????}
}
using?NGuestBook.IBLL;
namespace?NGuestBook.Factory
{
????/**//**//**////?<summary>
????///?業務邏輯層工廠,用于獲取相應的業務邏輯層對象
????///?使用Abstract?Factory設計模式+Facace設計模式+反射機制+緩存機制設計
????///?</summary>
????public?sealed?class?BLLFactory
????{
????????/**//**//**////?<summary>
????????///?獲取管理員業務邏輯層對象
????????///?</summary>
????????///?<returns>管理員業務邏輯層對象</returns>
????????public?static?IAdminBLL?CreateAdminBLL()
????????{
????????????return?(IAdminBLL)DependencyInjector.GetBLLObject("AdminBLL");
????????}
????????/**//**//**////?<summary>
????????///?獲取留言業務邏輯層對象
????????///?</summary>
????????///?<returns>留言業務邏輯層對象</returns>
????????public?static?IMessageBLL?CreateMessageBLL()
????????{
????????????return?(IMessageBLL)DependencyInjector.GetBLLObject("MessageBLL");
????????}
????????/**//**//**////?<summary>
????????///?獲取評論業務邏輯層對象
????????///?</summary>
????????///?<returns>評論業務邏輯層對象</returns>
????????public?static?ICommentBLL?CreateCommentBLL()
????????{
????????????return?(ICommentBLL)DependencyInjector.GetBLLObject("CommentBLL");
????????}
????}
}
之所以這樣做,是為了實現層與層之間的“可替換”式設計,例如,現在需要換一種方式實現數據訪問層,只要這個實現遵循了前面定義的數據訪問層接口,業務邏輯層和表示層不需要做任何改動,只需要改一下配置文件系統即可正常運行。另外,基于這種結構的系統,還可以實現并行開發。即不同開發人員可以專注于自己的層次,只有接口被定義好了,開發出來的東西就可以無縫連接。
在J2EE平臺上,主要使用Spring框架實現依賴注入。這里,我們將自己做一個依賴注入容器。
依賴注入的理論基礎是Abstract Factory設計模式,這里結合具體實例簡單介紹一下。
上圖以數據訪問層為例,展示了Abstract Factory模式的應用。如圖,現假設有針對Access和SQLServer兩種數據庫的數據訪問層,它們都實現了數據訪問層接口。每個數據訪問層有自己的工廠,所有工廠都實現自IDALFactory接口。而客戶類(這里就是業務邏輯層類)僅與工廠接口、數據訪問層接口耦合,而與具體類無關,這樣,只要通過配置文件確定實例化哪個工廠,就可以得到不同的數據訪問層。
?
然而,這種設計雖然可行,但是代碼比較冗余,因為這樣需要為數據訪問層的每一個實現編寫一個工廠,業務邏輯層也一樣。在以前,我們毫無辦法,但是,.NET平臺引入的反射機制,給我們提供了一種解決方案。使用反射,每個層只需要一個工廠,然后通過從配置文件中讀出程序集的名稱,動態加載相應類。另外,為了提高依賴注入機制的效率,這里引入緩存機制。下面來看具體實現。
?配置
首先,需要在Web工程的Web.config文件的<appSettings>節點下添加如下兩個項:
<add?key="DAL"?value=""/>
<add?key="BLL"?value=""/>
?
這兩個配置選項分別存儲要應用的數據訪問和也業務邏輯層的程序集名稱。value目前是空,是因為目前還沒有各個層次的具體實現。
實現緩存操作輔助類
為實現緩存操作,我們將緩存操作封裝成一個輔助類,放在Utility工程下,具體代碼如下:
?
using?System;using?System.Web;
using?System.Web.Caching;
namespace?NGuestBook.Utility
{
????/**//**//**////?<summary>
????///?輔助類,用于緩存操作
????///?</summary>
????public?sealed?class?CacheAccess
????{
????????/**//**//**////?<summary>
????????///?將對象加入到緩存中
????????///?</summary>
????????///?<param?name="cacheKey">緩存鍵</param>
????????///?<param?name="cacheObject">緩存對象</param>
????????///?<param?name="dependency">緩存依賴項</param>
????????public?static?void?SaveToCache(string?cacheKey,?object?cacheObject,?CacheDependency?dependency)
????????{
????????????Cache?cache?=?HttpRuntime.Cache;
????????????cache.Insert(cacheKey,?cacheObject,?dependency);
????????}
????????/**//**//**////?<summary>
????????///?從緩存中取得對象,不存在則返回null
????????///?</summary>
????????///?<param?name="cacheKey">緩存鍵</param>
????????///?<returns>獲取的緩存對象</returns>
????????public?static?object?GetFromCache(string?cacheKey)
????????{
????????????Cache?cache?=?HttpRuntime.Cache;
????????????return?cache[cacheKey];
????????}
????}
}
?
?
封裝依賴注入代碼
因為很多依賴注入代碼非常相似,為了減少重復性代碼,我們將可復用的代碼先封裝在一個類中。具體代碼如下(這個類放在Factory工程下):
?
?
using?System;using?System.Configuration;
using?System.Reflection;
using?System.Web;
using?System.Web.Caching;
using?NGuestBook.Utility;
namespace?NGuestBook.Factory
{
????/**//**//**////?<summary>
????///?依賴注入提供者
????///?使用反射機制實現
????///?</summary>
????public?sealed?class?DependencyInjector
????{
????????/**//**//**////?<summary>
????????///?取得數據訪問層對象
????????///?首先檢查緩存中是否存在,如果不存在,則利用反射機制返回對象
????????///?</summary>
????????///?<param?name="className">數據訪問類名稱</param>
????????///?<returns>數據訪問層對象</returns>
????????public?static?object?GetDALObject(string?className)
????????{
????????????/**//**//**////?<summary>
????????????///?取得數據訪問層名稱,首先檢查緩存,不存在則到配置文件中讀取
????????????///?緩存依賴項為Web.Config文件
????????????///?</summary>
????????????object?dal?=?CacheAccess.GetFromCache("DAL");
????????????if?(dal?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????dal?=?ConfigurationManager.AppSettings["DAL"];
????????????????CacheAccess.SaveToCache("DAL",?dal,?fileDependency);
????????????}
????????????/**//**//**////?<summary>
????????????///?取得數據訪問層對象
????????????///?</summary>
????????????string?dalName?=?(string)dal;
????????????string?fullClassName?=?dalName?+?"."?+?className;
????????????object?dalObject?=?CacheAccess.GetFromCache(className);
????????????if?(dalObject?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????dalObject?=?Assembly.Load(dalName).CreateInstance(fullClassName);
????????????????CacheAccess.SaveToCache(className,?dalObject,?fileDependency);
????????????}
????????????return?dalObject;
????????}
????????/**//**//**////?<summary>
????????///?取得業務邏輯層對象
????????///?首先檢查緩存中是否存在,如果不存在,則利用反射機制返回對象
????????///?</summary>
????????///?<param?name="className">業務邏輯類名稱</param>
????????///?<returns>業務邏輯層對象</returns>
????????public?static?object?GetBLLObject(string?className)
????????{
????????????/**//**//**////?<summary>
????????????///?取得業務邏輯層名稱,首先檢查緩存,不存在則到配置文件中讀取
????????????///?緩存依賴項為Web.Config文件
????????????///?</summary>
????????????object?bll?=?CacheAccess.GetFromCache("BLL");
????????????if?(bll?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????bll?=?ConfigurationManager.AppSettings["BLL"];
????????????????CacheAccess.SaveToCache("BLL",?bll,?fileDependency);
????????????}
????????????/**//**//**////?<summary>
????????????///?取得業務邏輯層對象
????????????///?</summary>
????????????string?bllName?=?(string)bll;
????????????string?fullClassName?=?bllName?+?"."?+?className;
????????????object?bllObject?=?CacheAccess.GetFromCache(className);
????????????if?(bllObject?==?null)
????????????{
????????????????CacheDependency?fileDependency?=?new?CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
????????????????bllObject?=?Assembly.Load(bllName).CreateInstance(fullClassName);
????????????????CacheAccess.SaveToCache(className,?bllObject,?fileDependency);
????????????}
????????????return?bllObject;
????????}
????}
}
| 實現工廠 |
?
?
using?System;using?NGuestBook.IDAL;
namespace?NGuestBook.Factory
{
????/**//**//**////?<summary>
????///?數據訪問層工廠,用于獲取相應的數據訪問層對象
????///?使用Abstract?Factory設計模式+Facace設計模式+反射機制+緩存機制設計
????///?</summary>
????public?sealed?class?DALFactory
????{
????????/**//**//**////?<summary>
????????///?獲取管理員數據訪問層對象
????????///?</summary>
????????///?<returns>管理員數據訪問層對象</returns>
????????public?static?IAdminDAL?CreateAdminDAL()???????
?{
????????????return?(IAdminDAL)DependencyInjector.GetDALObject("AdminDAL");
??????}
????????/**//**//**////?<summary>
????????///?獲取留言數據訪問層對象
????????///?</summary>
????????///?<returns>留言數據訪問層對象</returns>
????????public?static?IMessageDAL?CreateMessageDAL()
????????{
????????????return?(IMessageDAL)DependencyInjector.GetDALObject("MessageDAL");
????????}
????????/**//**//**////?<summary>
????????///?獲取評論數據訪問層對象
????????///?</summary>
????????///?<returns>評論數據訪問層對象</returns>
????????public?static?ICommentDAL?CreateCommentDAL()
????????{
????????????return?(ICommentDAL)DependencyInjector.GetDALObject("CommentDAL");
????????}
????}
}
?
using?System;using?NGuestBook.IBLL;
namespace?NGuestBook.Factory
{
????/**//**//**////?<summary>
????///?業務邏輯層工廠,用于獲取相應的業務邏輯層對象
????///?使用Abstract?Factory設計模式+Facace設計模式+反射機制+緩存機制設計
????///?</summary>
????public?sealed?class?BLLFactory
????{
????????/**//**//**////?<summary>
????????///?獲取管理員業務邏輯層對象
????????///?</summary>
????????///?<returns>管理員業務邏輯層對象</returns>
????????public?static?IAdminBLL?CreateAdminBLL()
????????{
????????????return?(IAdminBLL)DependencyInjector.GetBLLObject("AdminBLL");
????????}
????????/**//**//**////?<summary>
????????///?獲取留言業務邏輯層對象
????????///?</summary>
????????///?<returns>留言業務邏輯層對象</returns>
????????public?static?IMessageBLL?CreateMessageBLL()
????????{
????????????return?(IMessageBLL)DependencyInjector.GetBLLObject("MessageBLL");
????????}
????????/**//**//**////?<summary>
????????///?獲取評論業務邏輯層對象
????????///?</summary>
????????///?<returns>評論業務邏輯層對象</returns>
????????public?static?ICommentBLL?CreateCommentBLL()
????????{
????????????return?(ICommentBLL)DependencyInjector.GetBLLObject("CommentBLL");
????????}
????}
}
轉載于:https://www.cnblogs.com/dreamszx/archive/2008/08/01/1258068.html
總結
以上是生活随笔為你收集整理的.NET平台依赖注入机制及IoC的设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用命令导入、导出mysql数据
- 下一篇: (搬家文) c++引用深入探讨