`
黄继华
  • 浏览: 45899 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

.NET平台依赖注入机制及IoC的设计与实现

 
阅读更多

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

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

在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)相结合简洁实用的使用方式

    近日, 学习.NET平台下的依赖注入(IOC)和 面向切面(AOP)。 力求获得一种简洁实用的方法实现IOC和AOP相结合的使用方式。 查阅了多个技术资料。经过多次测试,基本达到目的。 IOC使用微软的 Microsoft.Practices....

    ASP.NET Core依赖注入系列教程之控制反转(IoC)

    主要给大家介绍了关于ASP.NET Core依赖注入系列教程之控制反转(IoC)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    .NET Autofac依赖注入

    依赖注入又称之为控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency ...

    依赖注入实现,及IOC容器Unity的小Demo

    在.NET开发中,Unity是一个常用的IOC(Inversion of Control,控制反转)容器,它可以帮助我们实现依赖注入。 首先,让我们了解依赖注入的三种主要方式: 1. 构造函数注入:这是最常见的注入方式,通过在类的构造...

    .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了

    最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式,为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中,但是在服务调用的时候总是获取到最后注入的那个方法的实现,这...

    Spring.Net IOC依赖注入原理流程解析

    Spring.Net IOC依赖注入原理流程解析 本文将详细介绍Spring.Net IOC依赖注入原理流程解析,通过示例代码介绍了非常详细,对大家的学习或者工作具有一定的参考学习价值。 一、什么是IOC? IOC(Inversion of ...

    spring.net依赖注入Demo

    **Spring.NET依赖注入(DI)和控制反转(IOC)概念** Spring.NET是一个针对.NET平台的开源框架,它引入了依赖注入(Dependency Injection,简称DI)和控制反转(Inversion of Control,简称IOC)的设计模式,使得...

    了解ASP.NET Core 依赖注入.doc

    .NET Core的依赖注入是通过`IServiceCollection`和`IServiceProvider`来实现的。`IServiceCollection`用于注册服务,而`IServiceProvider`则负责根据注册的服务创建实例。我们可以使用`AddTransient`、`AddSingleton...

    详解asp.net core 依赖注入

    依赖注入(Dependency Injection,简称DI)是软件设计中一种重要的模式,它有助于实现代码的高内聚和低耦合,从而提高系统的可测试性和可维护性。在ASP.NET Core中,依赖注入是核心架构的一部分,使得开发者能够轻松地...

    【ASP.NET编程知识】ASP.NET MVC实现依赖注入的完整过程.docx

    ASP.NET MVC 实现依赖注入的完整过程 ASP.NET MVC 实现依赖注入的完整过程是指在 ASP.NET MVC 框架中实现依赖注入(Dependency Injection,简称 DI)功能的完整过程。依赖注入是一种设计模式,目的是将对象之间的...

    ASP.NET MVC4中使用Unity Ioc Container 实例

    在MVC模式中,依赖注入(Dependency Injection,DI)是实现解耦和提高代码可测试性的重要技术之一。Unity IoC Container是Microsoft提供的一款轻量级的依赖注入容器,它可以帮助我们管理对象的生命周期,方便地注入...

    .net 轻量级ioc实现

    .NET轻量级IOC(Inversion of Control)容器的实现是一个重要的设计模式,它允许开发者将对象的创建和管理从应用程序的业务逻辑中分离出来,提高了代码的可测试性和可维护性。本文将深入探讨如何使用单个.CS文件实现...

    mvc4 ioc 依赖注入简单示例实现

    本文将深入探讨如何在ASP.NET MVC4框架下,结合Unity容器实现依赖注入,具体通过一个简单的示例来展示其实施过程。 首先,我们需要理解什么是IoC(Inversion of Control,控制反转)。IoC是一种编程范式,它反转了...

    【ASP.NET编程知识】.NET Unity IOC框架使用实例详解.docx

    .NET Unity IOC 框架是微软为企业应用提供的一种依赖注入(Dependency Injection,简称 DI)解决方案,主要用于解决软件设计中的耦合问题。IOC,即控制反转,是DI的一种形式,它将对象的创建和管理权交给专门的容器...

    【ASP.NET编程知识】.NET Core 3.0中WPF使用IOC的图文教程.docx

    通过以上步骤,你已经成功地在.NET Core 3.0的WPF应用中实现了依赖注入。这种做法使你的代码更加模块化,易于测试和维护。随着更多第三方库对.NET Core 3.0的支持,使用IOC来构建WPF应用将会变得更加便捷和强大。...

    ASP.NET+MVC+ENTLIB+LOG4NET+IOC

    **MVC (Model-View-Controller)** 是一种设计模式,广泛应用于ASP.NET中,用于分离应用程序的业务逻辑、用户界面和数据处理。模型负责管理数据和业务逻辑,视图负责展示数据,而控制器负责处理用户输入并协调模型和...

    asp.net+mvc+ef+ioc多语言通用后台框架

    Inversion of Control,通常与依赖注入(Dependency Injection,DI)一起讨论,是一种设计原则,旨在提高软件的灵活性和可测试性。在ASP.NET MVC中,IoC容器可以自动管理对象的生命周期和依赖关系,使得组件之间解耦...

    C#实现的IOC和AOP框架,供学习

    在现代软件开发中,依赖注入(IOC,Inversion of Control)和面向切面编程(AOP,Aspect-Oriented Programming)是两种非常重要的设计模式,它们有助于提高代码的可测试性、可维护性和模块化程度。这个名为...

    依赖注入那些事儿

    - **Spring.NET**:Spring.NET是.NET平台上的Spring框架,它提供了一整套企业级开发所需的工具和框架,包括依赖注入支持。 - **Unity**:Unity是一个由Microsoft开发的轻量级IoC Container,支持多种依赖注入模式,...

Global site tag (gtag.js) - Google Analytics