Unity容器在asp.net mvc中的IOC应用及AOP应用
《asp.net-mvc框架揭秘》一书中,有个示例,是使用unity容器来注入自定义的控制器工厂。代码示例可以自己去下载源码,在这里我就不说了。IOC容器的本质是解耦的实例化接口类,而如何做到解耦就是通过第三方容器来实例化,在这里是unity容器,而不是在项目中实例化接口类。实例化的方法无非就是反射,Emit,表达式树,委托等四个方法。Unity容器的IOC使用主要是三个个方法:Register,Resolver,Dispose。前者注册接口和接口类,后者将接口类的实例化转移到第三方容器中实现。而这里的Dispose却是有点文章了。如果单单是控制台的应用项目,就不必多说,如果是在mvc框架中的话,我们的接口类的资源释放应该放在什么地方合适呢?微软unity开发小组给我们做了很好的解释,原文:https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx
我们将Unity容器里面资源的释放与控制器的资源释放绑定在一起。如何用代码来表示?我们在基于Unity的控制器工厂中的GetControllerInstance中解析controllerType对象,而不是解析某个接口:
(IController)this.UnityContainer.Resolve(controllerType);
尽管Unity容器是IOC框架,我们还是可以使用unity来做AOP,可以参考的官方资料:(5 - Interception using Unity)。
我们主要是通过集成ICallHandler接口来实现AOP,这个接口是unity给我们提供的,这个接口主要就是一个Invoke方法。继承自ICallHandler接口的类(TCalHandler),当通过接口(TIOCInterface)开始调用类(TIOCImple)中的方法时,就会开始调用类(TCalHandler)的Invoke方法。
在Invoke中,如果调用getNext()方法就会调用IOCImple标注了属性的方法。如果你的C#基础比较扎实,你对C#中的一个重要知识点-特性(attribute)应该就会有印象以及一定的了解。asp.net-mvc框架中的过滤器就是基于attribute实现的。那么在这里也是,我们需要调用unity给我们提供的一个特性attribute-HandlerAttribute,在这里我们调用我们基于ICallHandler的类。
DI是为了解耦的实例化接口,而AOP是横向的注入一些逻辑,我们可以在AOP里面实现DI,unity中的AOP模块默认会给我们实现DI,一旦我们实现了AOP,就相当于实现了DI。我会挑一些代码片段来解释。代码来自<<asp.net-mvc框架揭秘>>的第14章S1401源码。首先我们实现自己自定义的控制器工厂:
public class UnityControllerFactory : DefaultControllerFactory
{
public IUnityContainer UnityContainer { get; private set; } public UnityControllerFactory(IUnityContainer unityContainer)
{
this.UnityContainer = unityContainer;
} protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (null == controllerType)
{
return null;
}
return (IController)this.UnityContainer.Resolve(controllerType);
}
}
之前说过的unity的DI对象 Resolve是在这里完成的。
我们定义了一个接口ITimeProvider和接口实现类DefaultTimeProvider,然后我们基于ICallHandler接口实现一个类:
public class CachingCallHandler : ICallHandler
{
public int Order { get ; set ; } public TimeSpan ExpirationTime { get; private set; } public static TimeSpan DefaultExpirationTime { get; private set; } public static Func<MethodBase, object[], string> CacheKeyGenerator { get; private set; } // 静态构造函数,只调用一次,并且是最先调用的
static CachingCallHandler()
{
DefaultExpirationTime = new TimeSpan(, , );
Guid prefix = Guid.NewGuid(); CacheKeyGenerator = (method, inputs) =>
{
StringBuilder sb = new StringBuilder(); sb.AppendFormat("{0}: ", prefix);
sb.AppendFormat("{0}: ", method.DeclaringType);
sb.AppendFormat("{0}: ", method.Name); if (inputs != null)
{
foreach (var input in inputs)
{
string hashCode = (input == null) ? "" : input.GetHashCode().ToString();
sb.AppendFormat("{0}: ", hashCode);
}
}
return sb.ToString().TrimEnd(':');
}; } public CachingCallHandler(TimeSpan? expirationTime=null)
{
this.ExpirationTime = expirationTime.HasValue ? expirationTime.Value : DefaultExpirationTime;
} public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
MethodInfo targetMethod = (MethodInfo)input.MethodBase; if(targetMethod.ReturnType == typeof(void))
{
return getNext()(input, getNext);
} object[] inputs = new object[input.Inputs.Count];
input.Inputs.CopyTo(inputs, );
string cacheKey = CacheKeyGenerator(targetMethod, inputs); object[] cachedResult = HttpRuntime.Cache.Get(cacheKey) as object[]; if (null == cachedResult)
{
IMethodReturn realReturn = getNext()(input, getNext);
if(null == realReturn.Exception)
{
HttpRuntime.Cache.Insert(cacheKey, new object[] { realReturn.ReturnValue }, null, DateTime.Now.Add(this.ExpirationTime), Cache.NoSlidingExpiration);
}
return realReturn;
}
return input.CreateMethodReturn(cachedResult[], new object[] { input.Arguments }); }
}
Invoke方法的调用是在ITimeProvider对象调用其内的接口时候触发调用的。
接下来基于HandlerAttribute来实现一个类:
public class CachingCallHandlerAttribute : HandlerAttribute
{
public TimeSpan? ExpirationTime { get; private set; } public CachingCallHandlerAttribute(string expirationTime ="")
{
if(!string.IsNullOrEmpty(expirationTime))
{
TimeSpan expirationTimeSpan;
if(!TimeSpan.TryParse(expirationTime, out expirationTimeSpan))
{
throw new ArgumentException("输入过期时间(TimeSpan) 不合法");
}
this.ExpirationTime = expirationTimeSpan;
}
} public override ICallHandler CreateHandler(IUnityContainer container)
{
return new CachingCallHandler(this.ExpirationTime) { Order = this.Order };
}
}
接下来我们Global.asax中,完成AOP的注入:
IUnityContainer UnityContainer= new UnityContainer()
.AddNewExtension<Interception>()
.RegisterType<ITimeProvider, DefaultTimeProvider>(); UnityContainer.Configure<Interception>()
.SetInterceptorFor<ITimeProvider>(new InterfaceInterceptor()); UnityControllerFactory controllerFactory = new UnityControllerFactory(UnityContainer); ControllerBuilder.Current.SetControllerFactory(controllerFactory);
最后就是使用了:
public class HomeController : Controller
{
public ITimeProvider TimeProvider;
public HomeController(ITimeProvider _time)
{
TimeProvider = _time;
} public void Index()
{
for (int i = ; i < ; i++)
{
Response.Write(string.Format("{0}: {1: hh:mm:ss}<br/>", "Utc", this.TimeProvider.GetCurrentTime(DateTimeKind.Utc)));
Thread.Sleep(); Response.Write(string.Format("{0}: {1: hh:mm:ss}<br/><br/>", "Local", this.TimeProvider.GetCurrentTime(DateTimeKind.Local)));
Thread.Sleep();
}
}
}
在这里TimeProvider调用期内的方法GetCurrentTime方法时就会调用Invoke方法。Invoke方法的参数GetNextHandlerDelegate类的变量在Invoke中的调用代表着真正的调用GetCurrentTime方法。其实我们可以这么实现:
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{ var retvalue = getNext()(input, getNext);
if(retvalue.Exception!=null)
{
Console.WriteLine("error");
}
return retvalue;
}
这种简单的实现是完全可以的。
建议看看微软官方的资料https://msdn.microsoft.com/en-us/library/ff647202.aspx
代码地址:链接:https://pan.baidu.com/s/1q98_Otwt1YC_00z_xcavIA 密码:b9pj
Unity容器在asp.net mvc中的IOC应用及AOP应用的更多相关文章
- IOC 容器在 ASP.NET MVC 中的应用
IOC 容器在 ASP.NET MVC 中的应用 IOC:Inversion Of Control 翻译为控制反转,我们在面向对象软件开发过程中,一个应用程序它的底层结构可能由N种不同的构件来相互协作 ...
- ASP.NET MVC中使用Unity进行依赖注入的三种方式
在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...
- 在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)
在 ASP.NET MVC 中充分利用 WebGrid https://msdn.microsoft.com/zh-cn/magazine/hh288075.aspx Stuart Leeks 下载代 ...
- 在 ASP.NET MVC 中使用 HTML Helpers 的那些事
在 ASP.NET MVC 中使用 HTML Helpers 方法,可以返回得到标准的 HTML 标签,就像 <input>.<button> 或者 <img> 等 ...
- [转]ASP.NET MVC中你必须知道的13个扩展点
本文转自:http://www.cnblogs.com/ejiyuan/archive/2010/03/09/1681442.html ScottGu在其最新的博文中推荐了Simone Chiaret ...
- ASP.NET Core中使用IOC三部曲(二.采用Autofac来替换IOC容器,并实现属性注入)
前言 本文主要是详解一下在ASP.NET Core中,自带的IOC容器相关的使用方式和注入类型的生命周期. 这里就不详细的赘述IOC是什么 以及DI是什么了.. emm..不懂的可以自行百度. 目录 ...
- Asp.net mvc 中Action 方法的执行(二)
[toc] 前面介绍了 Action 执行过程中的几个基本的组件,这里介绍 Action 方法的参数绑定. 数据来源 为 Action 方法提供参数绑定的原始数据来源于当前的 Http 请求,可能包含 ...
- Asp.net mvc 中Action 方法的执行(一)
[toc] 在 Aps.net mvc 应用中对请求的处理最终都是转换为对某个 Controller 中的某个 Action 方法的调用,因此,要对一个请求进行处理,第一步,需要根据请求解析出对应的 ...
- Asp.net mvc 中的 Controller 的激活
Controller 激活是指根据路由系统解析出来的 Controller 的名称创建 控制器(Controller)的过程,这里的控制器泛指实现了 IController 接口的类型 激活过程中的核 ...
随机推荐
- Git- 命令及使用
关于Git相关介绍这里就不介绍了,可转<Git- 简介>或者查看官网信息.这篇整理一下git相关的命令. 1) 远程仓库相关命令 克隆下载仓库:$ git clone git://gi ...
- BIgnum类的程序提交
日期:2018.7.19 星期四 博客期:002 这之前赶着做一个单机游戏的修改器忘了时间,不好意思啊!今天我就把Bignum类的源代码发出来,文件的话,我不知道怎样发,待我好好研究研究这个网站哈!因 ...
- day11 函数的位置形参,位置实参,可变长位置形参,关键字形参
今天内容 函数的参数详解 形参与实参 形参及形式参数,就是在定义函数是括号中指定的参数(本质就是一个名字) 实参及实际参数,指的是在调用函数是传入的参数)(本质就是一个值) 在调用函数是就会把形参和实 ...
- linux学习笔记:第二单元 UNIX和Linux操作系统概述
第二单元 UNIX和Linux操作系统概述 UNIX是什么 UNIX操作系统的特点 UNIX 与Linux的关系 GNU项目与自由软件 GUN计划 自由软件意味着什么 Linux简介 Linux是什么 ...
- MySQL数据库查询中的特殊命令
第一: MySQL的安装 下载MySQL软件,修改安装路径之后 安装数据库MySQL5.7.18 第一步:数据库MySQL5.7.18可以在官网上下载对应的版本,下载地址:http://www.f ...
- jenkins持续集成:定时构建语法
构建位置:选择或创建工程_设置_构建触发器 1. 定时构建语法:* * * * * (五颗星,多个时间点,中间用逗号隔开)第一个*表示分钟,取值0~59第二个*表示小时,取值0~23第三个*表示一个月 ...
- git bash here 的 ~/.bashrc 配置文件。和 vue/cli 3. 0 的 .vuerc文件(preset )
今天就来讲一下git有关的小技巧,.bashrc文件是用户配置文环境变量的文件,每次git bash会首先运行里面的内容 1.自动运行 每次进入git bash都会先读取.bashrc里面的内容,因此 ...
- shiro配合html页面完成细粒化权限控制
shiro配合html页面完成细粒化权限控制 原创 2016年10月04日 12:02:34 标签: shiro / 框架 / 界面 / 权限 8924 shiro是现在非常普遍使用的java权限框架 ...
- QQ登录用到的URL
//QQ 登陆页面的URL,client_id就是APP ID,会返回一个codehttps://graph.qq.com/oauth2.0/authorize?response_type=code& ...
- [转] iOS9系统自带字体
Family: Thonburi Font: Thonburi-Bold Font: Thonburi Font: Thonburi-Light 1 2 3 4 Family: Khmer Sanga ...