.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
ExpandedBlockStart.gifContractedBlock.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//**//**//// <summary>
    
/// 辅助类,用于缓存操作
    
/// </summary>

    public sealed class CacheAccess
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 将对象加入到缓存中
        
/// </summary>
        
/// <param name="cacheKey">缓存键</param>
        
/// <param name="cacheObject">缓存对象</param>
        
/// <param name="dependency">缓存依赖项</param>

        public static void SaveToCache(string cacheKey, object cacheObject, CacheDependency dependency)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            Cache cache 
= HttpRuntime.Cache;
            cache.Insert(cacheKey, cacheObject, dependency);
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 从缓存中取得对象,不存在则返回null
        
/// </summary>
        
/// <param name="cacheKey">缓存键</param>
        
/// <returns>获取的缓存对象</returns>

        public static object GetFromCache(string cacheKey)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            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
ExpandedBlockStart.gifContractedBlock.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//**//**//// <summary>
    
/// 依赖注入提供者
    
/// 使用反射机制实现
    
/// </summary>

    public sealed class DependencyInjector
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 取得数据访问层对象
        
/// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象
        
/// </summary>
        
/// <param name="className">数据访问类名称</param>
        
/// <returns>数据访问层对象</returns>

        public static object GetDALObject(string className)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//**//**//// <summary>
            
/// 取得数据访问层名称,首先检查缓存,不存在则到配置文件中读取
            
/// 缓存依赖项为Web.Config文件
            
/// </summary>

            object dal = CacheAccess.GetFromCache("DAL");
            
if (dal == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                CacheDependency fileDependency 
= new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                dal 
= ConfigurationManager.AppSettings["DAL"];
                CacheAccess.SaveToCache(
"DAL", dal, fileDependency);
            }


ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//**//**//// <summary>
            
/// 取得数据访问层对象
            
/// </summary>

            string dalName = (string)dal;
            
string fullClassName = dalName + "." + className;
            
object dalObject = CacheAccess.GetFromCache(className);
            
if (dalObject == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                CacheDependency fileDependency 
= new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                dalObject 
= Assembly.Load(dalName).CreateInstance(fullClassName);
                CacheAccess.SaveToCache(className, dalObject, fileDependency);
            }


            
return dalObject;
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 取得业务逻辑层对象
        
/// 首先检查缓存中是否存在,如果不存在,则利用反射机制返回对象
        
/// </summary>
        
/// <param name="className">业务逻辑类名称</param>
        
/// <returns>业务逻辑层对象</returns>

        public static object GetBLLObject(string className)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//**//**//// <summary>
            
/// 取得业务逻辑层名称,首先检查缓存,不存在则到配置文件中读取
            
/// 缓存依赖项为Web.Config文件
            
/// </summary>

            object bll = CacheAccess.GetFromCache("BLL");
            
if (bll == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                CacheDependency fileDependency 
= new CacheDependency(HttpContext.Current.Server.MapPath("Web.Config"));
                bll 
= ConfigurationManager.AppSettings["BLL"];
                CacheAccess.SaveToCache(
"BLL", bll, fileDependency);
            }


ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//**//**//// <summary>
            
/// 取得业务逻辑层对象
            
/// </summary>

            string bllName = (string)bll;
            
string fullClassName = bllName + "." + className;
            
object bllObject = CacheAccess.GetFromCache(className);
            
if (bllObject == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                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
ExpandedBlockStart.gifContractedBlock.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//**//**//// <summary>
    
/// 数据访问层工厂,用于获取相应的数据访问层对象
    
/// 使用Abstract Factory设计模式+Facace设计模式+反射机制+缓存机制设计
    
/// </summary>

    public sealed class DALFactory
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 获取管理员数据访问层对象
        
/// </summary>
        
/// <returns>管理员数据访问层对象</returns>

        public static IAdminDAL CreateAdminDAL()       
ExpandedSubBlockStart.gifContractedSubBlock.gif 
{
            
return (IAdminDAL)DependencyInjector.GetDALObject("AdminDAL");
      }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 获取留言数据访问层对象
        
/// </summary>
        
/// <returns>留言数据访问层对象</returns>

        public static IMessageDAL CreateMessageDAL()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return (IMessageDAL)DependencyInjector.GetDALObject("MessageDAL");
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 获取评论数据访问层对象
        
/// </summary>
        
/// <returns>评论数据访问层对象</returns>

        public static ICommentDAL CreateCommentDAL()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return (ICommentDAL)DependencyInjector.GetDALObject("CommentDAL");
        }

    }

}

 

using System;
using NGuestBook.IBLL;

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


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 获取留言业务逻辑层对象
        
/// </summary>
        
/// <returns>留言业务逻辑层对象</returns>

        public static IMessageBLL CreateMessageBLL()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return (IMessageBLL)DependencyInjector.GetBLLObject("MessageBLL");
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//**//**//// <summary>
        
/// 获取评论业务逻辑层对象
        
/// </summary>
        
/// <returns>评论业务逻辑层对象</returns>

        public static ICommentBLL CreateCommentBLL()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return (ICommentBLL)DependencyInjector.GetBLLObject("CommentBLL");
        }

    }

}

转载于:https://www.cnblogs.com/dreamszx/archive/2008/08/01/1258068.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/411643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php嵌套查询mysql语句_mysql 查询嵌套

问题描述 为使讨论简单易懂&#xff0c;我将问题稍作简化&#xff0c;去掉诸多的背景。 从前有一个皇帝&#xff0c;他有50个妃子&#xff0c;这些妃子很没有天理的给他生了100,000个儿子&#xff0c;于是&#xff0c;皇帝很苦恼&#xff0c;海量的儿子很难管理&#xff0c;而且…

征途pak文件修改_传奇技能,第十四祭:装备属性修改与增加新装备

技能献祭&#xff0c;Get 新技能&#xff1a;传奇技能——应用篇&#xff0c;增加新装备与绑特效跟航家学技能&#xff0c;用正式服带你飞&#xff0c;底部有配套学习资源场景&#xff1a;游戏中装备的属性是可以修改的&#xff0c;基础攻防属性可以直接在物品数据库中修改&…

本题要求实现一个用选择法对整数数组进行简单排序的函数。_通俗易懂讲 Python 算法:快速排序...

原文&#xff1a;https://stackabuse.com/quicksort-in-python/作者&#xff1a;Marcus Sanatan译者&#xff1a;老齐欢迎在 bilibili 搜索 freeCodeCamp 官方账号或者直接访问 https://space.bilibili.com/335505768 观看我们的技术视频介绍快速排序是一种流行的排序算法&…

vscode标记_高效扩展工具让 VS Code 如虎添翼

Codelf 变量命名神器Star&#xff1a;10688https://github.com/unbug/codelf新建项目&#xff0c;变量&#xff0c;类&#xff0c;方法&#xff0c;接口都需要命名&#xff0c;一个好的命名可以一眼看出这个地方的功能&#xff0c;CodeIf 一键起名不再难&#xff0c;输入关键词…

CSS 有关Position = absolute (绝对定位 是相对于谁而言)

css中有绝对定位法&#xff0c;以前一直搞不懂绝对定位是相对于谁而言的绝对定位。 现在搞清楚了&#xff0c;不是相对于父元素&#xff0c;也不是相对于BODY。 而是相对于所属元素树中&#xff0c;相邻最近的那个显示标识了position属性的元素。 比如 Code<div id"a&q…

mysql gui vim_vim(一): 小技巧

1) 如何yank字符然后再查找 ( / Ctrl - R 0 ) The most recently yanked text will be stored in the 0 and registers (if no register was explicitly specified e.g. by xy ). Then you can paste the text of any that register in the last line (eith1) 如何yank字符然后…

LeetCode Smallest Range

数据范围是3500,3500也就是说n的平方是可以接受的。这里告诉你就是有序的,也就是在提醒你可能会是一个类似于二分的算法,所以的话其实基于这两个认识的话我们就可以利用一个枚举叫二分的算法来解决这道题。怎么做呢&#xff1f;就首先的话我们要枚举一端,一端的话我们可以把所有…

Web前端3.0时代,“程序猿”如何“渡劫升仙”

Web前端入行门槛低&#xff0c;很多人在成为前端工程师后很容易进入工作的舒适区&#xff0c;认为该熟悉的业务已熟悉了&#xff0c;然后就是重复用轮子&#xff0c;这样很容易让自己的成长处于原地打转以及低水平重复的状态。 想要不被行业抛弃&#xff0c;就要努力提升自己。…

mysql用 fifo 记录日志_MySQL一丢丢知识点的了解

1. MySQL体系结构从概念上讲&#xff0c;数据库是文件的集合&#xff0c;是依照某种数据模型组织起来并存放于二级存储器中的数据集合&#xff1b;数据库实例是程序&#xff0c;是位于用户与操作系统之间的一层数据管理软件&#xff0c;用户对数据库数据的任何操作&#xff0c;…

HttpHandler

概述HttpHandler是一个HTTP请求的真正处理中心&#xff0c;也正是在这个HttpHandler容器中&#xff0c;ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行&#xff0c;并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。 IHttpHandler是什么 I…

小程序云开发搜索功能的实现正则_码code | 如何借助小程序云开发实现小程序支付功能...

转载来源&#xff1a;编程小石头我们在做小程序支付相关的开发时&#xff0c;总会遇到这些难题。小程序调用微信支付时&#xff0c;必须要有自己的服务器&#xff0c;有自己的备案域名&#xff0c;有自己的后台开发。这就导致我们做小程序支付时的成本很大。本节就来教大家如何…

python接口自动化(二十五)--unittest断言——下(详解)

简介 本篇还是回归到我们最初始的话题&#xff0c;想必大家都忘记了&#xff0c;没关系看这里&#xff1a;传送门 没错最初的话题就是登录&#xff0c;由于博客园的登录机制改变了&#xff0c;本篇以我找到的开源免费的登录API为案例&#xff0c;结合 unittest 框架写 2 个用例…

mysql-bin磁盘满数据库重启不_liunx磁盘空间满了,导致mysql数据库无法启动

如何启动/遏制/重启MySQLA、1、启动圆式1、哄骗 service 启动&#xff1a;service mysqld start2、哄骗 mysqld 脚本启动&#xff1a;/etc/inint.d/mysqld start3、哄骗 safe_mysqld 启动&#xff1a;safe_mysqld&二、遏制1、哄骗 service 启动&#xff1a;service mysqld …

[导入]C# Tips 2 右键单击listBox时弹出右键菜单并选中单击的行

C#,Listbox,右键,菜单,选中文章来源:http://blog.csdn.net/geyunfei_hit/archive/2008/07/16/2661153.aspx 转载于:https://www.cnblogs.com/geyunfei/archive/2008/10/08/1306335.html

python真的可以减少工作强度_用Python写几行代码,一分钟搞定一天工作量,同事直呼:好家伙!...

前几天有一个读者说最近要整理几千份文件&#xff0c;头都要整秃了&#xff0c;不知道能不能用Python解决&#xff0c;我们来看一下&#xff0c;你也可以思考一下。由于涉及文件私密所以具体内容已做脱敏处理。大概是这样&#xff0c;一个文件夹下有多份会议通知信息(本文以 7 …

Jmeter之逻辑控制器(Logic Controller)

一、简单控制器&#xff08;Simple Controller&#xff09;&#xff1a; 作用&#xff1a;这是Jmeter里最简单的一个控制器&#xff0c;它可以让我们组织我们的采样器和其它的逻辑控制器&#xff08;分组功能&#xff09;&#xff0c;提供一个块的结构和控制&#xff0c;并不具…

python需要掌握的词汇量_北大保安英语词汇量1.5万,会用Python编程,孟母三迁真有道理...

这就是良好学习环境的重要性啊&#xff0c;不然你以为“孟母三迁”是咋来的&#xff1f;人家孟母为了孩子有个好的学习环境&#xff0c;宁愿搬三次家。而这些保安小哥一步到位&#xff0c;直接就进入了无数人梦寐以求的最高学府&#xff0c;想不牛都不行啊。01、北大是最高学府…

Visual Studio Team System 2008 安装失败

微软的东西 看样子也没怎么测试就发布了。。。 [10/27/08,23:05:56] Microsoft .NET Framework 3.5: [2] Error code 1603 for this component means "安装时发生严重错误"[10/27/08,23:05:58] Microsoft .NET Framework 3.5: [2] Setup Failed on component Microso…

【题解】序列

题目描述 一个长度为k的整数序列b1&#xff0c;b2&#xff0c;...&#xff0c;bk&#xff08;1≤b1≤b2≤...≤bk≤N&#xff09;称为“好序列”当且仅当后一个数是前一个数的倍数&#xff0c;即bi1是bi的倍数对任意的i&#xff08;1≤i≤k-1&#xff09;成立。 给定N和k&#…

Struts2 文件上传

JSP界面&#xff1a; 必须把表单的enctype属性改为 multipart/form-data才能上传 Action&#xff1a; 程序如果多人使用&#xff0c;必须保证文件名是唯一&#xff0c;文件名相同会覆盖掉原来的文件&#xff0c;所以使用时间作为文件名。可以把生成的文件名直接存入数据库中&am…