之所以这样做,是为了实现层与层之间的“可替换”式设计,例如,现在需要换一种方式实现数据访问层,只要这个实现遵循了前面定义的数据访问层接口,业务逻辑层和表示层不需要做任何改动,只需要改一下配置文件系统即可正常运行。另外,基于这种结构的系统,还可以实现并行开发。即不同开发人员可以专注于自己的层次,只有接口被定义好了,开发出来的东西就可以无缝连接。
在J2EE平台上,主要使用Spring框架实现依赖注入。这里,我们将自己做一个依赖注入容器。
依赖注入的理论基础是Abstract Factory设计模式,这里结合具体实例简单介绍一下。

然而,这种设计虽然可行,但是代码比较冗余,因为这样需要为数据访问层的每一个实现编写一个工厂,业务逻辑层也一样。在以前,我们毫无办法,但是,.NET平台引入的反射机制,给我们提供了一种解决方案。使用反射,每个层只需要一个工厂,然后通过从配置文件中读出程序集的名称,动态加载相应类。另外,为了提高依赖注入机制的效率,这里引入缓存机制。下面来看具体实现。
配置
首先,需要在Web工程的Web.config文件的<appSettings>节点下添加如下两个项:
<add key="DAL" value=""/>
<add key="BLL" value=""/>
 <add key="BLL" value=""/>
这两个配置选项分别存储要应用的数据访问和也业务逻辑层的程序集名称。value目前是空,是因为目前还没有各个层次的具体实现。
实现缓存操作辅助类
 为实现缓存操作,我们将缓存操作封装成一个辅助类,放在Utility工程下,具体代码如下:
 using System;
using System; using System.Web;
using System.Web; using System.Web.Caching;
using System.Web.Caching;
 namespace NGuestBook.Utility
namespace NGuestBook.Utility

 {
{
 /**//**//**//// <summary>
    /**//**//**//// <summary> /// 辅助类,用于缓存操作
    /// 辅助类,用于缓存操作 /// </summary>
    /// </summary> public sealed class CacheAccess
    public sealed class CacheAccess
 
     {
{
 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 将对象加入到缓存中
        /// 将对象加入到缓存中 /// </summary>
        /// </summary> /// <param name="cacheKey">缓存键</param>
        /// <param name="cacheKey">缓存键</param> /// <param name="cacheObject">缓存对象</param>
        /// <param name="cacheObject">缓存对象</param> /// <param name="dependency">缓存依赖项</param>
        /// <param name="dependency">缓存依赖项</param> public static void SaveToCache(string cacheKey, object cacheObject, CacheDependency dependency)
        public static void SaveToCache(string cacheKey, object cacheObject, CacheDependency dependency)
 
         {
{ Cache cache = HttpRuntime.Cache;
            Cache cache = HttpRuntime.Cache; cache.Insert(cacheKey, cacheObject, dependency);
            cache.Insert(cacheKey, cacheObject, dependency); }
        }

 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 从缓存中取得对象,不存在则返回null
        /// 从缓存中取得对象,不存在则返回null /// </summary>
        /// </summary> /// <param name="cacheKey">缓存键</param>
        /// <param name="cacheKey">缓存键</param> /// <returns>获取的缓存对象</returns>
        /// <returns>获取的缓存对象</returns> public static object GetFromCache(string cacheKey)
        public static object GetFromCache(string cacheKey)
 
         {
{ Cache cache = HttpRuntime.Cache;
            Cache cache = HttpRuntime.Cache;
 return cache[cacheKey];
            return cache[cacheKey]; }
        } }
    } }
} 
 
封装依赖注入代码
 因为很多依赖注入代码非常相似,为了减少重复性代码,我们将可复用的代码先封装在一个类中。具体代码如下(这个类放在Factory工程下):
 using System;
using System; using System.Configuration;
using System.Configuration; using System.Reflection;
using System.Reflection; using System.Web;
using System.Web; using System.Web.Caching;
using System.Web.Caching; using NGuestBook.Utility;
using NGuestBook.Utility;
 namespace NGuestBook.Factory
namespace NGuestBook.Factory

 {
{
 /**//**//**//// <summary>
    /**//**//**//// <summary> /// 依赖注入提供者
    /// 依赖注入提供者 /// 使用反射机制实现
    /// 使用反射机制实现 /// </summary>
    /// </summary> public sealed class DependencyInjector
    public sealed class DependencyInjector
 
     {
{
 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 取得数据访问层对象
        /// 取得数据访问层对象 /// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象
        /// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象 /// </summary>
        /// </summary> /// <param name="className">数据访问类名称</param>
        /// <param name="className">数据访问类名称</param> /// <returns>数据访问层对象</returns>
        /// <returns>数据访问层对象</returns> public static object GetDALObject(string className)
        public static object GetDALObject(string className)
 
         {
{
 /**//**//**//// <summary>
            /**//**//**//// <summary> /// 取得数据访问层名称,首先检查缓存,不存在则到配置文件中读取
            /// 取得数据访问层名称,首先检查缓存,不存在则到配置文件中读取 /// 缓存依赖项为Web.Config文件
            /// 缓存依赖项为Web.Config文件 /// </summary>
            /// </summary> object dal = CacheAccess.GetFromCache("DAL");
            object dal = CacheAccess.GetFromCache("DAL"); if (dal == null)
            if (dal == null)
 
             {
{ CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config")); dal = ConfigurationManager.AppSettings["DAL"];
                dal = ConfigurationManager.AppSettings["DAL"]; CacheAccess.SaveToCache("DAL", dal, fileDependency);
                CacheAccess.SaveToCache("DAL", dal, fileDependency); }
            }

 /**//**//**//// <summary>
            /**//**//**//// <summary> /// 取得数据访问层对象
            /// 取得数据访问层对象 /// </summary>
            /// </summary> string dalName = (string)dal;
            string dalName = (string)dal; string fullClassName = dalName + "." + className;
            string fullClassName = dalName + "." + className; object dalObject = CacheAccess.GetFromCache(className);
            object dalObject = CacheAccess.GetFromCache(className); if (dalObject == null)
            if (dalObject == null)
 
             {
{ CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config")); dalObject = Assembly.Load(dalName).CreateInstance(fullClassName);
                dalObject = Assembly.Load(dalName).CreateInstance(fullClassName); CacheAccess.SaveToCache(className, dalObject, fileDependency);
                CacheAccess.SaveToCache(className, dalObject, fileDependency); }
            }
 return dalObject;
            return dalObject; }
        }

 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 取得业务逻辑层对象
        /// 取得业务逻辑层对象 /// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象
        /// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象 /// </summary>
        /// </summary> /// <param name="className">业务逻辑类名称</param>
        /// <param name="className">业务逻辑类名称</param> /// <returns>业务逻辑层对象</returns>
        /// <returns>业务逻辑层对象</returns> public static object GetBLLObject(string className)
        public static object GetBLLObject(string className)
 
         {
{
 /**//**//**//// <summary>
            /**//**//**//// <summary> /// 取得业务逻辑层名称,首先检查缓存,不存在则到配置文件中读取
            /// 取得业务逻辑层名称,首先检查缓存,不存在则到配置文件中读取 /// 缓存依赖项为Web.Config文件
            /// 缓存依赖项为Web.Config文件 /// </summary>
            /// </summary> object bll = CacheAccess.GetFromCache("BLL");
            object bll = CacheAccess.GetFromCache("BLL"); if (bll == null)
            if (bll == null)
 
             {
{ CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config")); bll = ConfigurationManager.AppSettings["BLL"];
                bll = ConfigurationManager.AppSettings["BLL"]; CacheAccess.SaveToCache("BLL", bll, fileDependency);
                CacheAccess.SaveToCache("BLL", bll, fileDependency); }
            }

 /**//**//**//// <summary>
            /**//**//**//// <summary> /// 取得业务逻辑层对象
            /// 取得业务逻辑层对象 /// </summary>
            /// </summary> string bllName = (string)bll;
            string bllName = (string)bll; string fullClassName = bllName + "." + className;
            string fullClassName = bllName + "." + className; object bllObject = CacheAccess.GetFromCache(className);
            object bllObject = CacheAccess.GetFromCache(className); if (bllObject == null)
            if (bllObject == null)
 
             {
{ CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                CacheDependency fileDependency = new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config")); bllObject = Assembly.Load(bllName).CreateInstance(fullClassName);
                bllObject = Assembly.Load(bllName).CreateInstance(fullClassName); CacheAccess.SaveToCache(className, bllObject, fileDependency);
                CacheAccess.SaveToCache(className, bllObject, fileDependency); }
            }
 return bllObject;
            return bllObject; }
        } }
    } }
}
| 实现工厂 | 
 using System;
using System; using NGuestBook.IDAL;
using NGuestBook.IDAL;
 namespace NGuestBook.Factory
namespace NGuestBook.Factory

 {
{
 /**//**//**//// <summary>
    /**//**//**//// <summary> /// 数据访问层工厂,用于获取相应的数据访问层对象
    /// 数据访问层工厂,用于获取相应的数据访问层对象 /// 使用Abstract Factory设计模式+Facace设计模式+反射机制+缓存机制设计
    /// 使用Abstract Factory设计模式+Facace设计模式+反射机制+缓存机制设计 /// </summary>
    /// </summary> public sealed class DALFactory
    public sealed class DALFactory
 
     {
{
 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 获取管理员数据访问层对象
        /// 获取管理员数据访问层对象 /// </summary>
        /// </summary> /// <returns>管理员数据访问层对象</returns>
        /// <returns>管理员数据访问层对象</returns> public static IAdminDAL CreateAdminDAL()
        public static IAdminDAL CreateAdminDAL()       
 
  {
{ return (IAdminDAL)DependencyInjector.GetDALObject("AdminDAL");
            return (IAdminDAL)DependencyInjector.GetDALObject("AdminDAL"); }
      }
 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 获取留言数据访问层对象
        /// 获取留言数据访问层对象 /// </summary>
        /// </summary> /// <returns>留言数据访问层对象</returns>
        /// <returns>留言数据访问层对象</returns> public static IMessageDAL CreateMessageDAL()
        public static IMessageDAL CreateMessageDAL()
 
         {
{ return (IMessageDAL)DependencyInjector.GetDALObject("MessageDAL");
            return (IMessageDAL)DependencyInjector.GetDALObject("MessageDAL"); }
        }

 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 获取评论数据访问层对象
        /// 获取评论数据访问层对象 /// </summary>
        /// </summary> /// <returns>评论数据访问层对象</returns>
        /// <returns>评论数据访问层对象</returns> public static ICommentDAL CreateCommentDAL()
        public static ICommentDAL CreateCommentDAL()
 
         {
{ return (ICommentDAL)DependencyInjector.GetDALObject("CommentDAL");
            return (ICommentDAL)DependencyInjector.GetDALObject("CommentDAL"); }
        } }
    } }
}
 using System;
using System; using NGuestBook.IBLL;
using NGuestBook.IBLL;
 namespace NGuestBook.Factory
namespace NGuestBook.Factory

 {
{
 /**//**//**//// <summary>
    /**//**//**//// <summary> /// 业务逻辑层工厂,用于获取相应的业务逻辑层对象
    /// 业务逻辑层工厂,用于获取相应的业务逻辑层对象 /// 使用Abstract Factory设计模式+Facace设计模式+反射机制+缓存机制设计
    /// 使用Abstract Factory设计模式+Facace设计模式+反射机制+缓存机制设计 /// </summary>
    /// </summary> public sealed class BLLFactory
    public sealed class BLLFactory
 
     {
{
 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 获取管理员业务逻辑层对象
        /// 获取管理员业务逻辑层对象 /// </summary>
        /// </summary> /// <returns>管理员业务逻辑层对象</returns>
        /// <returns>管理员业务逻辑层对象</returns> public static IAdminBLL CreateAdminBLL()
        public static IAdminBLL CreateAdminBLL()
 
         {
{ return (IAdminBLL)DependencyInjector.GetBLLObject("AdminBLL");
            return (IAdminBLL)DependencyInjector.GetBLLObject("AdminBLL"); }
        }

 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 获取留言业务逻辑层对象
        /// 获取留言业务逻辑层对象 /// </summary>
        /// </summary> /// <returns>留言业务逻辑层对象</returns>
        /// <returns>留言业务逻辑层对象</returns> public static IMessageBLL CreateMessageBLL()
        public static IMessageBLL CreateMessageBLL()
 
         {
{ return (IMessageBLL)DependencyInjector.GetBLLObject("MessageBLL");
            return (IMessageBLL)DependencyInjector.GetBLLObject("MessageBLL"); }
        }

 /**//**//**//// <summary>
        /**//**//**//// <summary> /// 获取评论业务逻辑层对象
        /// 获取评论业务逻辑层对象 /// </summary>
        /// </summary> /// <returns>评论业务逻辑层对象</returns>
        /// <returns>评论业务逻辑层对象</returns> public static ICommentBLL CreateCommentBLL()
        public static ICommentBLL CreateCommentBLL()
 
         {
{ return (ICommentBLL)DependencyInjector.GetBLLObject("CommentBLL");
            return (ICommentBLL)DependencyInjector.GetBLLObject("CommentBLL"); }
        } }
    } }
}