我们设计的分层架构,层与层之间应该是松散耦合的。因为是单向单一调用,所以,这里的“松散耦合”实际是指上层类不能具体依赖于下层类,而应该依赖于下层提供的一个接口。这样,上层类不能直接实例化下层中的类,而只持有接口,至于接口所指变量最终究竟是哪一个类,则由依赖注入机制决定。
之所以这样做,是为了实现层与层之间的“可替换”式设计,例如,现在需要换一种方式实现数据访问层,只要这个实现遵循了前面定义的数据访问层接口,业务逻辑层和表示层不需要做任何改动,只需要改一下配置文件系统即可正常运行。另外,基于这种结构的系统,还可以实现并行开发。即不同开发人员可以专注于自己的层次,只有接口被定义好了,开发出来的东西就可以无缝连接。
在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"); } } }
|
分享到:
相关推荐
近日, 学习.NET平台下的依赖注入(IOC)和 面向切面(AOP)。 力求获得一种简洁实用的方法实现IOC和AOP相结合的使用方式。 查阅了多个技术资料。经过多次测试,基本达到目的。 IOC使用微软的 Microsoft.Practices....
主要给大家介绍了关于ASP.NET Core依赖注入系列教程之控制反转(IoC)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
依赖注入又称之为控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency ...
最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式,为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中,但是在服务调用的时候总是获取到最后注入的那个方法的实现,这...
主要介绍了Spring.Net IOC依赖注入原理流程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
依赖注入,全称是“依赖注入到容器”, 容器(IOC容器)是一个设计模式,它也是个对象,你把某个类(不管有多少依赖关系)放入这个容器中,可以“解析”出这个类的实例。所以依赖注入就是把有依赖关系的类放入容器...
使用Unity.MVC3在asp.net mvc3中实现依赖注入 有具体使用步骤
spring.net是为.net开发者提供的一个控制反转操作框架也称作依赖注入。 此demo仅提供参考spring.net mvc+三层
最近在学ASP.NET MVC项目中使用Ioc,选用了Unity作为依赖注入的容器组件,在网上找了相关的文章简单实现了依赖注入,但想用文件配置的方式进行容器注入的注册,发现相关的文章实现的方式不适用,因为网上的文章大多...
在asp.net mvc中,无论是什么代码逻辑分层,最终的表现层为Controller层,所以我们注入点就是在Controller中,这里我们需要替换默认的ControllerFactory,扫描代码中标记需要注入的对象,进行实例化注入 public ...
【IOC 控制反转】Android 视图依赖注入 ( 视图依赖注入步骤 | 视图依赖注入代码示例 ) https://hanshuliang.blog.csdn.net/article/details/120404805 博客源码快照
【IOC 控制反转】Android 布局依赖注入 ( 布局依赖注入步骤 | 布局依赖注入代码示例 ) https://hanshuliang.blog.csdn.net/article/details/120402953 博客源码快照
综述 2.系统需求分析及数据库设计 3.架构概要设计 4.实体类的实现 5.接口的设计与实现 6.依赖注入及IoC的设计与实现
主要介绍了.NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
.NET平台下的依赖注入(IOC)和 面向切面(AOP)。 力求获得一种简洁实用的方法实现IOC和AOP相结合的使用方式。 查阅了多个技术资料。经过多次测试,基本达到目的。 IOC使用微软的 Microsoft.Practices.Unity,AOP ...
说到属性注入,我们就不得不提一下 DI(Dependency Injection),即依赖注入,用过 ASP.NET Core 的同学相信对这个词不会陌生。ASP.NET Core 自带了一个IOC容器,且程序运行也是基于这个容器建立起来的,在 Startup 里...
体验.net2.0的优雅(四):Provider、策略、控制反转和依赖注入 泛型最佳实践 asp.net 2.0下嵌套masterpage页的可视化编辑 C# 2.0与泛型 动态调用对象的属性和方法——性能和灵活性兼备的方法 泛型技巧系列:用泛型...
基础篇包括:控制反转,环境搭建,实现简易IOC框架,对象的创建,容器中对象作用域,依赖注入,依赖对象的注入,集合类型的注入等 所有代码都是基于.net平台的C#语言实现的,资源整理自互联网,欢迎爱好学习研究框架...
①依赖注入模式、O/RM对象映射模式; ②IOC、循环依赖都是如何设计和实现的。 阅读建议: 此资源以开发WebApi框架,最基本的DDD领域分层,让初学者对DDD的一个切面有所了解,同时内置了详细的运行说明,只需本地部署...