在前面我们学习到的是Unity依赖注入(DI)与统一容器来松散耦合,这个设计已经对我们系统带来了很多的好处。但是我们还会想尝试和遵循单一职责,开放封闭原则。比如我们不应该在我们的Business层去实现日志、校验、缓存、异常处理等工作,Unity的Interception可以帮助我们横切关注点(Crosscutting concerns 即AOP),来独立处理这些关注点。
什么是横切关注点(AOP)?横切关注点(AOP)是关注影响应用程序的许多 区域 。例如,你可能需要将信息写入日志文件在应用程序许多不同的区域,横切关注点(AOP)可以帮助你构建一致的应用程序方式与应用程序业务。
常见的LOB应用程序的横切关注点包括:
1.日记(Log)
2.校验( Validation )
3.异常 处理( Exception handling )
4.瞬时故障处理( Transient fault handling )
5.权限处理( Authentication and authorization )
6.缓存( Caching )
7.性能监控( Performance monitoring )
8.加密( Encryption )
9.映射( Mapping )
10.压缩( Compression )
在使用 Unity.Interception 以前我们先自己写一个简单的AOP:
1.业务接口
/// <summary> /// 接口 /// </summary> public interface ITalk { void talk(string msg); }
2.业务实现
public class PeopleTalk : ITalk { private string username; private int age; public string UserName { get { return username; } } public int Age { get { return age; } } public PeopleTalk(string userName, int age) { this.username = userName; this.age = age; } public virtual void talk(string msg) { Console.WriteLine(msg + "!你好,我是" + username + ",我的年龄" + age); } }
3.代理对象
public class TalkProxy : ITalk { private ITalk talker; public TalkProxy(ITalk talker) { this.talker = talker; } public void talk(string msg) { talker.talk(msg); } public void talk(string msg, string singName) { talker.talk(msg); sing(singName); } public void sing(string singName) { Console.WriteLine("唱歌:" + singName); } }
4.调用
class Program { static void Main(string[] args) { #region 静态代理 ITalk people = new PeopleTalk("AOP", 18); people.talk("No ProXY Test!"); Console.WriteLine("---------------------------------"); TalkProxy talker = new TalkProxy(people); talker.talk("ProXY Test", "代理"); #endregion } }
代理模式是一种简单的AOP,talk是一个切面,我们可以在代理类中添加日志、校验、异常处理等等。这样我们就实现了,核心关注点与横切关注点的分离。正如Avanade公司的高级方案架构师Adam Magee所说,AOP的核心思想就是”将应用程序中的商业逻辑同对其提供支持的通用服务进行分离“。
下面我们来看看 Unity.Interception是如何现实AOP的
1.在Unity中实现 IInterceptionBehavior 接口
/// <summary> /// Unity为我们提供了一个IInterceptionBehavior接口需要实现这个接口 /// 接口为我们提供了三个方式(GetRequiredInterfaces、Invoke、WillExecute)实现 /// WillExecute表示是否执行该行为,如果是false这个方法被调用时,不会被捕捉。因为我们总是要执行的,所以为true /// GetRequiredInterfaces将你想要的接口类型和行为联系起来,我们暂时不需要,所以返回Type.EmptyTypes /// Invoke执行方式接口 /// </summary> public class LoggingInterceptionBehavior : IInterceptionBehavior { public bool WillExecute { get { return true; } } public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("Method: {0}", input.MethodBase.Name); Console.WriteLine("参数:"); for (var i = 0; i < input.Arguments.Count; i++) { Console.WriteLine("{0}: {1}", input.Arguments.ParameterName(i), input.Arguments[i]); } Console.WriteLine("执行前"); var result = getNext()(input, getNext);//在这里执行方法 if (result.Exception != null) { //发生错误记录日志 Console.WriteLine(String.Format("Method {0} threw exception {1} at {2}", input.MethodBase, result.Exception.Message, DateTime.Now.ToLongTimeString())); } Console.WriteLine("执行后"); return result; } }
2.调用
class Program { static void Main(string[] args) { UnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); container.RegisterType<ITalk, PeopleTalk>( new InjectionConstructor("AOP", 18), new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingInterceptionBehavior>()); ITalk talker = container.Resolve<ITalk>(); talker.talk("ProXY Test!"); } }
以上基本完成了简单的Unity.Interception
当然在Unity中不只有InterfaceInterceptor一种拦截器,它还包含其它两种拦截器: TransparentProxyInterceptor 与 VirtualMethodInterceptor
这里就不详细介绍就提一下这三种:
InterfaceInterceptor只要是继承接口的方法都会被拦截。
TransparentProxyInterceptor只要是继承类使用的方法都会被拦截。
VirtualMethodInterceptor 意思是虚方法拦截器,继承类的方法必须是Virtual的,和继承类必须是公开的。满足这两个条件即可
----------------------------------------------------------------------------------------------------------------
同时在这里我还是没有回答在我Unity4.0的使用中“一只老菜鸟”所提的问题,不过我会努力的
以上是本人比较初级的处理,主要用于本人学习Unity的一个记录
如果有不懂的可以先查看
Unity 依赖注入之一
Unity 依赖注入之二