.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,一经查实,立即删除!

相关文章

工作377-处理url拼接里面的参数方法

function GetRequest() {var url location.search; //获取url中"?"符后的字串var theRequest new Object();if (url.indexOf("?") ! -1) {var str url.substr(1);strs str.split("&");for(var i 0; i < strs.length; i ) {theRequ…

1020.数字识别

来源&#xff1a;oj.noi.cn时间限制: 1000 ms 空间限制: 262144 KB题目描述输入一个不多于四位的正整数&#xff0c;求出它是几位数&#xff0c;并分别打印出各位上的数字。输入输入一个不多于四位的正整数x。输出第一行输出x的位数num&#xff0c;接下来num行从高位到低位输出…

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

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

工作378-封装axios方法

const apiBaseUrl http://118.178.180.86:9000const service axios.create({baseURL: apiBaseUrl,timeout: 10000 });/*拦截器获取token地址*/ service.interceptors.request.use(function(config) {var Request new Object();Request GetRequest();let tokenRequest.token…

爬虫之request

目录 爬虫基本流程request和responserequestresponse演示解析方式requests库基本get请求1. 基本写法2. 带参数get请求3. 解析json4. 获取二进制数据5. 添加headers基本post请求响应状态码判断&#xff1a;高级操作beautifulsoup库爬取汽车之家示例爬虫基本流程 发起请求&#x…

工作379-回调日期补0操作

var data econsole.log(this.continuousDays, "continuousDays")data data.setDate(data.getDate() this.continuousDays);data new Date(e);console.log(data, "data")let dateYear1 data.getFullYear(); //获取年console.log(dateYear1, "date…

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

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

8月18日 小雨

小爱&#xff0c;昨天你睡的很可爱 呵呵 我今天没晚&#xff0c;居然提前20分钟自己醒了。 刚来公司&#xff0c;就收到经理通知&#xff0c;中午大家要去开发区吃饭&#xff0c;下午事都处理完就可能放假&#xff0c;HOHO。 提前告诉小爱&#xff0c;不要着急。 我爱你 转载于…

python tornado对接权限中心的sdk封装

# -*- coding: utf-8 -*- import jsonimport requests import logging as loggerfrom python.akskapp.scripts.api.baseHandler import Rclass AuthSdk(object):# 登录def loginToAuthcenter(self, username, password):resp Noneheaders {"Content-Type": "a…

mysql事务模式怎么查_Mysql InnoDB中的查询事务模式与锁定select ..for update

在 InnoDB 的行锁中使用所谓的 next-key locking。这就意味着&#xff0c;除了索引记录外&#xff0c;InnoDB 还可以锁定该索引记录前部“间隙” (gap) 以阻塞其它用户在索引记录前部的直接插入。next-key lock 意思是锁定一个索引记录以及该记录之前的间隙(gap)。gap lock 就是…

[jQuery] jQuery中如何将数组转化为json字符串,然后再转化回来?

[jQuery] jQuery中如何将数组转化为json字符串&#xff0c;然后再转化回来&#xff1f; var typeOf obj > Object.prototype.toString.call(obj); typeOf([1]); // "[object Array]" typeOf($([1])); // "[object Object]" $([1]).toArray();个人简…

.NET反射、委托技术与设计模式

转自&#xff1a;http://hi.baidu.com/nanashitou/blog/item/ad7346eed769ffffb2fb958a.html 1 反射技术与设计模式 反射&#xff08;Reflection&#xff09;是.NET中的重要机制&#xff0c;通过放射&#xff0c;可以在运行时获得.NET中每一个类型&#xff08;包括类、…

python之yield的一些应用

生成器 yield是用于生成器。生成器通俗的认为&#xff0c;在一个函数中&#xff0c;使用了yield来代替return的位置的函数&#xff0c;就是生成器。它不同于函数的使用方法是&#xff1a;函数使用return来进行返回值&#xff0c;每调用一次&#xff0c;返回一个新加工好的数据返…

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

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

[jQuery]JQuery一个对象可以同时绑定多个事件,这是如何实现的?

JQuery一个对象可以同时绑定多个事件&#xff0c;这是如何实现的&#xff1f; ①$(document).ready(function() {$("button").bind({click: function() {$("p").slideToggle()},mouseover: function() {$("body").css("background-color&q…

张娟娟(为奥运冠军名字作诗)

张娟娟&#xff08;为奥运冠军名字作诗&#xff09;——代腾飞 2008年8月18日 于成都张弓搭箭射靶心娟娟俊美胜古今娟弓即破他人梦百步穿杨改乾坤 转载于:https://www.cnblogs.com/daitengfei/archive/2008/08/25/1276023.html

IO_ADDRESS()的实现【转】

上面我们说了如何去在系统中自己实现一个设置系统寄存器的一个方法&#xff0c;上面归根到底要进行物理地址到虚拟地址的映射 现在我们就说说IO_ADDRESS()的实现 #define __REG32ALI&#xff08;addr) (*((volatile unsigned long *)((addr) - ALI_REGS_PHYS_BASE ALI_REGS_V…

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

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

[html] 如何实现标题栏闪烁、滚动的效果

[html] 如何实现标题栏闪烁、滚动的效果 定时器背景设置个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

各种数据库连接字符串

1、ACCESS数据库连接set conn Server.CreateObject("ADODB.Connection")conn.Open("driver{Microsoft Access Driver (*.mdb)};dbq" &_Server.MapPath("person.mdb"))set rs conn.Execute( "SELECT * FROM grade" )For I 0 to …