使用场景?
很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用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 = "123123123123" }; 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[0] as User; if (user.Password.Length < 10) { 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[0] 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 = 1)] //注册校验 [LogHandlerAttribute(Order = 2)] //日志处理 [ExceptionHandlerAttribute(Order = 3)] //遗产处理 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里会有详细的介绍。