基于.NET平台的分层架构实战(六)——依赖注入机制及IoC的设计与实现[转]

原文:http://www.cnblogs.com/leoo2sk/archive/2008/06/19/1225223.html

  我们设计的分层架构,层与层之间应该是松散耦合的。因为是单向单一调用,所以,这里的“松散耦合”实际是指上层类不能具体依赖于下层类,而应该 依赖于下层提供的一个接口。这样,上层类不能直接实例化下层中的类,而只持有接口,至于接口所指变量最终究竟是哪一个类,则由依赖注入机制决定。

   之所以这样做,是为了实现层与层之间的“可替换”式设计,例如,现在需要换一种方式实现数据访问层,只要这个实现遵循了前面定义的数据访问层接口,业务 逻辑层和表示层不需要做任何改动,只需要改一下配置文件系统即可正常运行。另外,基于这种结构的系统,还可以实现并行开发。即不同开发人员可以专注于自己 的层次,只有接口被定义好了,开发出来的东西就可以无缝连接。

  在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

1using 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}

 

时间: 2024-10-11 03:55:32

基于.NET平台的分层架构实战(六)——依赖注入机制及IoC的设计与实现[转]的相关文章

基于LAMP平台的网站架构(或Web系统架构)

1.网站架构的前提(或者说需求) 我们公司是一电子商务的网站,因为线下家具建材项目的推广需求,从而有了我们公司的这个线上网站,在这里我贴一张公司的网站架构图. 总体来说网站规模不是太大,注册人数在150万左右,并发最大也就1500,图上架构没有压力,嘿嘿! 2.公司网站架构的发展 a.起初只有一台服务器,放在公司内部我要这里称为架构0(如图)(出口用防火墙进行NAT转换) 注:我相信大家对这个应该很熟悉,嘿嘿!我们学习的时候都这样做,用一台虚拟机搭一个LAMP平台做测试与开始用,只不过公司里的服

会话EJB系列(六)依赖注入

在本文的开始之前,先给大家介绍一个概念"依赖". 什么是依赖呢? 简单的说,就是A组件需要调用B组件,B组件需要调用C组件,C组件需要调用D组件-..这种调用称为:依赖! 在最早的应用程序中,依赖关系时通过new关键字来实现的.A组件依赖B组件,就是在A组件中显示的new一个B组件.缺点: 1.硬编码,耦合性强,难以维护.A组件只需要B组件中的方法,不必关心B组件的创建问题! 2.频繁的创建对象,导致系统开销增大. 上面的这种缺点,直接催生了'工厂模式'. 在工厂模式中,A组件依赖B组

Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之权限管理系统(2) 功能及实体设计 3 Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL 4 Asp.Net Core 项目实战之权限管理系统(4) 依赖注入.仓储.服务的多项目分层实现 5 Asp.Net Core 项目实

领域驱动设计(DDD)分层架构的三种模式

模式一:四层架构 1.User Interface为用户界面层(或表示层),负责向用户显示信息和解释用户命令.这里指的用户可以是另一个计算机系统,不一定是使用用户界面的人.2.Application为应用层,定义软件要完成的任务,并且指挥表达领域概念的对象来解决问题.这一层所负责的工作对业务来说意义重大,也是与其它系统的应用层进行交互的必要渠道.应用层要尽量简单,不包含业务规则或者知识,而只为下一层中的领域对象协调任务,分配工作,使它们互相协作.它没有反映业务情况的状态,但是却可以具有另外一种状

你真的了解分层架构吗?——写给被PetShop&quot;毒害&quot;的朋友们

一叶障目 .NET平台上的分层架构(很多朋友称其为“三层架构”),似乎是一个长盛不衰的话题.经常看到许多朋友对其进行分析.探讨.辩论甚至是抨击.笔者在仔细阅读了大量这方面文章后,认为许多朋友在分层架构的理解上存在两个比较大的偏颇: 1.没有从本质角度去理解分层的内涵,而只是了解其表象. 2.对分层架构的理解过于狭隘,只是少数概念,而又不够深入. 许多朋友言“分层”则必称“DAL”.“BLL”.“表示层”等概念,殊不知“DAL”的内部还有“Data Source 架构模式”.“Object-Rel

你真的了解分层架构吗?

你真的了解分层架构吗?-写给被PetShop...... 文章转载自:http://www.cnblogs.com/szp11/archive/2010/09/17/1829048.html 昵称:大肚小男人 ps:本文是作者与2010年写的关于分层架构的理解,其中的一些理念值得学习. NET平台上的分层架构(很多朋友称其为"三层架构"),似乎是一个长盛不衰的话题.经常看到许多朋友对其进行分析.探讨.辩论甚至是抨击.笔者在仔细阅读了大量这方面文章后,认为许多朋友在分层架构的理解上存在两

快如闪电、超轻量级的基于.Net平台的依赖注入框架Ninject

一.为什么要使用依赖注入框架 依赖注入框架也叫IoC容器.它的作用使类与类之间解耦 我们看看为什么要用依赖注入框架,举个几个梨子: 1,高度耦合的类 有一个Order类,Order类是用于订单操作的,DataAccess使用的sqlserver的方式查询订单.看看代码: public class Order { private DataAccess dataAccess = new DataAccess(); public string QueryOrder() { return dataAcc

Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播公开课

本课程采用Q Q群直播方式进行直播,价值99元视频课程免费直播.完整的基于Swift项目实战,手把手教你做一个Swift版iPhone计算器.(直播过程也有惊喜!)直播Q Q群:362298485(直播时点击群视频即可进入直播课堂)直播时间:8月26日(周二),9月2日(周四),每天20:00-22:00欢迎咨询客服Q Q:1575716557直播后希望继续深入学习了解本课程可在51CTO学院购买本课程,定价99元.购买课程更有惊喜:买课程送书,送优惠券了! 购买本课程赠送关东升老师价值69元国

Swift项目实战-基于分层架构的多版本iPhone计算器-免费直播公开课邀您参与

Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播课 好消息:买本课程送相关讲师图书+50金币课程优惠券!还有更好消息,为了回馈新老学员,本次采取直播免费,录播收费的形式哦~! 购买本课程赠送关东升老师价值69元国内第一本<Swift开发指南>,并且赠送50元优惠券一张.69+50>99.(购买课程后请联系客服QQ:1575716557) 本课程采用QQ群直播方式进行直播,直播免费看了,完整的基于Swift项目实战,手把手教你做一个Swift版iPhone计算器. 直播