C# Unity依赖注入利用Attribute实现AOP功能
使用场景?
很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用OOP的思想, 在原有的功能上进行扩展。
那么有没有一种东西, 可以实现当我们需要扩展这个功能的时候, 在不修改原来的功能代码的情况下实现, 这就是下面要说的到Unity。
1.准备工作
为项目添加NuGet包, 搜索Unity并且安装。
在使用的项目中添加Unity的相关引用
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;
2.假设场景
刚才上面说道, Unity可实现在不修改原功能的情况下, 添加额外的扩展功能。在我们的实际开发中, 也可以举个简单的例子。
当我们去做一个用户注册的功能, 最初的版本是完成了基本的注册功能, 后来我们需要扩展了, 给他加上注册校验, 日志处理, 和异常捕捉的几个功能, 那么接下来就演示, 如何用Unity给功能扩展。
3.如何使用
首先, 我们定义好一个最原始的注册功能
public static void Show()
{
User user = new User()
{
Name = "Eleven",
Password = ""
};
IUserProcessor porcessor = new UserProcessor();
porcessor.RegUser(user); //简单的用户注册
}
public interface IUserProcessor
{
void RegUser(User user);
} public class UserProcessor : IUserProcessor//MarshalByRefObject,
{
public void RegUser(User user)
{
Console.WriteLine("注册。");
}
}
接下来, 我们要对这个注册进行扩展了, 添加注册校验, 日志处理, 和异常捕捉的几个功能。
1.先定义3个特性与对应的特性行为实现, 分别是注册, 日志, 和异常。
public class UserHandlerAttribute : HandlerAttribute //注册校验
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
ICallHandler handler = new UserHandler() { Order = this.Order };
return handler;
}
} public class LogHandlerAttribute : HandlerAttribute //日志处理
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogHandler() { Order = this.Order };
}
} public class ExceptionHandlerAttribute : HandlerAttribute //异常处理
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new ExceptionHandler() { Order = this.Order };
}
}
对应的每个特性的实现行为, 分别实现 注册校验, 日志记录, 与 异常处理
public class UserHandler : ICallHandler //注册校验的行为
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
User user = input.Inputs[] as User;
if (user.Password.Length < )
{
return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));
}
Console.WriteLine("参数检测无误"); IMethodReturn methodReturn = getNext.Invoke().Invoke(input, getNext); return methodReturn;
}
} public class LogHandler : ICallHandler //日志处理的行为
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
User user = input.Inputs[] as User;
string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
Console.WriteLine("日志已记录,Message:{0},Ctime:{1}", message, DateTime.Now);
return getNext()(input, getNext);
}
} public class ExceptionHandler : ICallHandler //异常处理的行为
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
if (methodReturn.Exception == null)
{
Console.WriteLine("无异常");
}
else
{
Console.WriteLine("异常:{0}", methodReturn.Exception.Message);
}
return methodReturn;
}
}
按照现在思路, 我们要把这上面写好的几个功能添加在原来的注册功能上, 首先, 我们回到最开始定义接口的地方, 给接口添加我们定义按的3个特性
[UserHandlerAttribute(Order = )] //注册校验
[LogHandlerAttribute(Order = )] //日志处理
[ExceptionHandlerAttribute(Order = )] //遗产处理
public interface IUserProcessor
{
void RegUser(User user);
} //PS: 在上面的特性声明中, 每个对应的Order 这个属于排序, 相对于一个行为的执行顺序, 这个内部是Unity的一个实现, 所以我们使用的过程中只需要声明好标量即可。
然后, 我们在定义好的注册方法中, 首先声明一个Unity容器UnityContainer , 然后注册其上面的接口 IUserProcessor, 最后调用其接口的注册方法。
//声明一个容器
IUnityContainer container = new UnityContainer(); //声明UnityContainer并注册IUserProcessor
container.RegisterType<IUserProcessor, UserProcessor>(); container.AddNewExtension<Interception>().Configure<Interception>()
.SetInterceptorFor<IUserProcessor>(new InterfaceInterceptor());
IUserProcessor userprocessor = container.Resolve<IUserProcessor>();
userprocessor.RegUser(user); //调用注册方法。
最后, 我们看一下实际效果, 很轻松的实现了用于注册时候扩展其他更多的行为
小结:
不难发现, Unity的实现 主要以在接口上定义的特性与实现行为 与其内部Unity容器的结合 实现的AOP功能。
因为上面是属于静态的写法, 便于学习, 真正的实现AOP可动态配置, 在IOC里会有详细的介绍。
C# Unity依赖注入利用Attribute实现AOP功能的更多相关文章
- Unity 依赖注入之二
1. 构造子注入 1.1 构造子注入初级代码 container.RegisterType<IMyWork, MyWork>(new InjectionConstructor(new Bo ...
- Unity依赖注入使用详解
写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...
- WPF PRISM开发入门二(Unity依赖注入容器使用)
这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点 ...
- C# Unity依赖注入
简介: 控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的手中,在这个过程中你不是一个控制者而是一个请求者,依赖于容器提供给你的资源,控制权落到了容器 ...
- Unity 依赖注入
关于Ioc的框架有很多,比如astle Windsor.Unity.Spring.NET.StructureMap,我们这边使用微软提供的Unity做示例,你可以使用Nuget添加Unity,也可以引 ...
- c# Unity依赖注入WebService
1.IOC与DI简介 IOC全称是Inversion Of Control(控制反转),不是一种技术,只是一种思想,一个重要的面相对象编程的法则,它能知道我们如何设计出松耦合,更优良的程序.传统应用程 ...
- 使用Microsoft.Practices.Unity 依赖注入
Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...
- 使用Microsoft.Practices.Unity 依赖注入 转载https://www.cnblogs.com/slardar1978/p/4205394.html
Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...
- DDD实战8_2 利用Unity依赖注入,实现接口对应实现类的可配置
1.在Util类库下新建DIService类 /// <summary> /// 创建一个类,对应在配置文件中配置的DIServices里面的对象的 key /// </summar ...
随机推荐
- 特定位取反(js实现)
去华为面试的时候.没有做好准备工作.面试的流程没有问清也没有查,结果一过去就让上机做题,着实有点措手不及.笔者是擅长前端的Java Webproject师啊,主要的底层编程知识早已生疏了.机试题碰到了 ...
- 智课雅思短语---一、be no exception
智课雅思短语---一.be no exception 一.总结 一句话总结:…也不例外? …be no exception 1.经济的快速发展? the rapid development of ec ...
- python requests请求卡住问题
最近经常接到别人反馈某个爬虫工具程序没有正常运行,需要下载的资讯数据也没有及时进行收录. 刚开始以为可能是机器的问题,偶尔机器会出现程序运行中途卡住的情况. 但随着异常的情况越来越频繁,我便只好去排查 ...
- 原生js模拟jquery中的addClass和removeClass方法
js代码: //添加类 function addClass(obj,className) { if(obj.className == '') { //如果没有class obj.className = ...
- gitlab-ce-11.0.1 安装及汉化
1.添加gitlab源(我这里使用了清华大学的源)cat <<EOF> /etc/yum.repos.d/gitlab-ce.repo[gitlab-ce]name=gitlab-c ...
- gcc---C/C++ 编译器
gcc命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点.现在很多程序员都应用GCC,怎样才能更好的应用GCC.目前,GCC可以用 ...
- myeclipse中断点调试
在代码最左端,也就是行号位置处双击.会出现一个实心小圆点.即增加的断点.debug启动程序,就会运行到断点处: 按F5是进去方法里面. 按F6是一步一步走, 按F7是跳出方法里面(按F5后再按F7就跳 ...
- Hbuilder开发app实战-识岁06-face++的js实现【完结】
前言 因为识岁app比較简单.所以这节就完结吧, 当然另一些能够优化完好的地方,可是个人兴趣不是非常大, 有想继续完好的,源代码在这里:https://github.com/uikoo9/shisui ...
- C++ 递归位置排列算法及其应用
废话不多说,我们先看一下位置排序的算法: #include <iostream> using namespace std; int n = 0; int m = 2; int l = 0; ...
- vue2.0 transition用法
html: <div id="demo"> <button v-on:click="show = !show"> Toggle < ...