Unity,一个轻量级的可扩展的依赖注入容器,主要用于Aop(面向切面编程),在网上找了很多资料,看完还是一脸懵逼,写这篇文件主要是为了总结经验 按照自己的理解把unity的用法展示出来,方便自己和各位读者学习,话不多说,直接切入正题。
1.新建控制台工程
2.打开Vs NuGet 包管理工具,搜索unity,将下图红框内的所有包全部安装
3.创建实体类,代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Aborlen.Model { /// <summary> /// 用户信息 /// </summary> public class UserInfo { /// <summary> /// 用户Id /// </summary> public int Id { get; set; } /// <summary> /// 用户名 /// </summary> public string Name { get; set; } /// <summary> /// 用户密码 /// </summary> public string Password { get; set; } } }
4.创建接口
using Aborlen.Model; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Aborlen.Interface { /// <summary> /// 用户操作接口 /// </summary> public interface IUserProcessor { /// <summary> /// 注册用户 /// </summary> /// <param name="user"></param> void RegUser(UserInfo user); /// <summary> /// 获取用户 /// </summary> /// <param name="user"></param> /// <returns></returns> UserInfo GetUser(UserInfo user); } }
5.创建用户注册业务逻辑
using Aborlen.Interface; using Aborlen.Model; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Aborlen.Bll { /// <summary> /// 用户业务 /// </summary> public class UserProcessor : IUserProcessor { /// <summary> /// 注册用户 /// </summary> /// <param name="user"></param> public void RegUser(UserInfo user) { Console.WriteLine($"用户:{user.Name}已注册。"); } /// <summary> /// 获取用户 /// </summary> /// <param name="user"></param> /// <returns></returns> public UserInfo GetUser(UserInfo user) { return user; } } }
6.创建Aop扩展方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace Aborlen.AopExtension { /// <summary> /// 扩展Aop方法(模拟插入日志) /// </summary> public class LogBeforeBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { #region 此处编写需要添加的业务逻辑(写日志逻辑) Console.WriteLine("*************************日志****************************");//模拟写日志 #endregion return getNext().Invoke(input, getNext);// 执行实例方法(必须调用),如果先调用实例方法,再执行扩展操作,则需要先调用getNext().Invoke(input, getNext) 方法 。 } public bool WillExecute { get { return true; } } } }
7.创建配置文件(Unity.config)
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> </configSections> <unity> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> <containers> <!--容器名称,保持与代码种的容器名称一致--> <container name="aopContainer"> <extension type="Interception"/> <!--实例接口命名空间以及程序集;实例命名空间以及程序集--> <register type="Aborlen.Interface.IUserProcessor,Aborlen.Interface" mapTo="Aborlen.Bll.UserProcessor,Aborlen.Bll"> <interceptor type="InterfaceInterceptor"/> <!--扩展的方法名称--> <interceptionBehavior type="Aborlen.AopExtension.LogBeforeBehavior, Aborlen.AopExtension"/> </register> </container> </containers> </unity> </configuration>
8.Unity调用
using Aborlen.Interface; using Aborlen.Model; using Microsoft.Practices.Unity.Configuration; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity; namespace MyAop { class Program { static void Main(string[] args) { UserInfo user = new UserInfo() { Id=1, Name = "Aborlen", Password = "888888888888888899999999" }; //创建容器 IUnityContainer container = new UnityContainer(); ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); fileMap.ExeConfigFilename = Path.Combine(new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.Parent.FullName + "\\Unity.Config"); Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); configSection.Configure(container, "aopContainer");//容器名称,保持与配置文件一致 IUserProcessor processor = container.Resolve<IUserProcessor>(); processor.RegUser(user); UserInfo userNew1 = processor.GetUser(user); Console.WriteLine("********************结束***************************"); Console.ReadLine(); } } }
运行结果如下:
写日志成功。
注意事项:
扩展
1.方法结果缓存
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace Aborlen.AopExtension { /// <summary> /// 执行缓存方法 /// </summary> public class CachingBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } private static Dictionary<string, object> CachingBehaviorDictionary = new Dictionary<string, object>(); public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("CachingBehavior"); string key = $"{input.MethodBase.Name}_{Newtonsoft.Json.JsonConvert.SerializeObject(input.Inputs)}"; if (CachingBehaviorDictionary.ContainsKey(key)) { return input.CreateMethodReturn(CachingBehaviorDictionary[key]);//缓存存在,直接返回缓存结果 } else { //缓存不存在,执行方法并保存缓存结果 IMethodReturn result = getNext().Invoke(input, getNext); if (result.ReturnValue != null) CachingBehaviorDictionary.Add(key, result.ReturnValue); return result; } } public bool WillExecute { get { return true; } } } }
2.方法异常处理
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace Aborlen.AopExtension { /// <summary> /// 方法异常处理 /// </summary> public class ExceptionLoggingBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { IMethodReturn methodReturn = getNext()(input, getNext); Console.WriteLine("ExceptionLoggingBehavior"); if (methodReturn.Exception == null) { Console.WriteLine("无异常"); } else { Console.WriteLine($"异常:{methodReturn.Exception.Message}"); } return methodReturn; } public bool WillExecute { get { return true; } } } }
3.方法执行后操作
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace Aborlen.AopExtension { /// <summary> /// 方法执行后操作 /// </summary> public class LogAfterBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { IMethodReturn methodReturn = getNext()(input, getNext);//执行后面的全部动作 Console.WriteLine("LogAfterBehavior"); Console.WriteLine(input.MethodBase.Name); foreach (var item in input.Inputs) { Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item)); //反射&序列化获取更多信息 } Console.WriteLine("LogAfterBehavior" + methodReturn.ReturnValue); return methodReturn; } public bool WillExecute { get { return true; } } } }
4.方法参数检查(用于敏感词过滤,参数长度检查等)
using Aborlen.Model; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace Aborlen.AopExtension { /// <summary> /// 参数检查(敏感词过滤等场景) /// </summary> public class ParameterCheckBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("ParameterCheckBehavior"); UserInfo user = input.Inputs[0] as UserInfo; if (user.Password.Length < 10) { //返回一个异常 return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位")); } else { Console.WriteLine("参数检测无误"); return getNext().Invoke(input, getNext); } } public bool WillExecute { get { return true; } } } }
5.扩展后的配置文件
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> </configSections> <unity> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> <containers> <!--容器名称,保持与代码种的容器名称一致--> <container name="aopContainer"> <extension type="Interception"/> <!--实例接口命名空间以及程序集;实例命名空间以及程序集--> <register type="Aborlen.Interface.IUserProcessor,Aborlen.Interface" mapTo="Aborlen.Bll.UserProcessor,Aborlen.Bll"> <interceptor type="InterfaceInterceptor"/> <!--扩展的方法名称--> <!--方法异常处理--> <interceptionBehavior type="Aborlen.AopExtension.ExceptionLoggingBehavior, Aborlen.AopExtension"/> <!-- 执行缓存方法--> <interceptionBehavior type="Aborlen.AopExtension.CachingBehavior, Aborlen.AopExtension"/> <!--方法执行前相关操作--> <interceptionBehavior type="Aborlen.AopExtension.LogBeforeBehavior, Aborlen.AopExtension"/> <!--参数检查--> <interceptionBehavior type="Aborlen.AopExtension.ParameterCheckBehavior, Aborlen.AopExtension"/> <!--方法执行后操作--> <interceptionBehavior type="Aborlen.AopExtension.LogAfterBehavior, Aborlen.AopExtension"/> </register> </container> </containers> </unity> </configuration>
最后给出源代码,方便读者测试
百度网盘:https://pan.baidu.com/s/1UAZ935ktOu2YbEm9eUx8oA
提取码:u2td