第七节:WebApi与Unity整合进行依赖注入和AOP的实现
一. IOC和DI
1. 通过Nuget引入Unity程序集。
PS:【版本:5.8.6】
2. 新建DIFactory类,用来读取Unity的配置文件并创建Unity容器,需要注意的是DIFactory类需要声明成单例。
PS:这里采用静态构造函数(必须是无参的)的形式来实现单例,MVC框架的那个框架采用的是 双if+lock锁的形式实现的单例,结果都一样。
代码分享:
1 ///2 /// 依赖注入工厂(单例的 采用静态构造函数) 3 /// 读取Unity的配置文件,并创建Unity容器 4 /// 需要引入程序集“System.Configuration” 5 /// 6 public class DIFactory 7 { 8 private static IUnityContainer _Container = null; 9 static DIFactory() 10 { 11 //1. 固定的4行代码读取配置文件 12 ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); 13 fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路径 14 Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); 15 UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); 16 //2. Unity层次的步骤 17 _Container = new UnityContainer(); 18 //加载节点的名称为"apiContainer" 19 section.Configure(_Container, "apiContainer"); 20 } 21 22 /// 23 /// 对外开放函数,用来获取Unity容器 24 /// 25 /// 26 public static IUnityContainer GetContainer() 27 { 28 return _Container; 29 } 30 }
3. 新建UnityDependencyResolver类,用来自定义控制器实例化工厂.
特别注意:该类这里实现的是IDependencyResolver接口,来自WebApi下的程序集,而非MVC,所以和MVC下的写法有区别.
代码分享:
1 public class UnityDependencyResolver : IDependencyResolver 2 { 3 private IUnityContainer _IUnityContainer = null; 4 public UnityDependencyResolver(IUnityContainer unityContainer) 5 { 6 this._IUnityContainer = unityContainer; 7 } 8 9 ///UnityDependencyResolver10 /// 获取单个服务 11 /// 12 /// 13 /// 14 public object GetService(Type serviceType) 15 { 16 try 17 { 18 return this._IUnityContainer.Resolve(serviceType); 19 } 20 catch (ResolutionFailedException ex)//因为会累计构造多个对象,很多是没有去扩展,直接null就行 21 { 22 return null; 23 } 24 } 25 26 public IEnumerable<object> GetServices(Type serviceType) 27 { 28 try 29 { 30 return this._IUnityContainer.ResolveAll(serviceType); 31 } 32 catch (ResolutionFailedException) 33 { 34 return new List<object>(); 35 } 36 } 37 38 public IDependencyScope BeginScope()//每次请求 39 { 40 var child = this._IUnityContainer.CreateChildContainer(); 41 return new UnityDependencyResolver(child); 42 } 43 44 public void Dispose() 45 { 46 this._IUnityContainer.Dispose(); 47 } 48 }
4. 新建CfgFiles文件夹和UnityConfig.xml文件,该xml文件需要改属性为“始终复制”。
代码分享:
<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> configSections> <unity> <containers> <container name="apiContainer"> <register type="WebApiBasic.Interface.ITestService,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService,01-WebApiBasic"/> <register type="WebApiBasic.Interface.ITestService2,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService2,01-WebApiBasic"/> container> containers> unity> configuration>
5. 在WebApiConfig文件中进行配置,把webapi的DependencyResolver换成自己的Unity版本的
config.DependencyResolver = new UnityDependencyResolver(DIFactory.GetContainer());
6. 新建Service文件夹和Interface文件夹,分别创建TestService类和ITestService接口,并去UnityConfig.xml文件中进行注册(上述xml里已经注册好了)。
代码如下:
1 public class TestService : ITestService 2 { 3 public string GetInfor() 4 { 5 return "我是ypf"; 6 } 7 }
1 public interface ITestService 2 { 3 string GetInfor(); 4 }
7. 在控制器中进行构造函数的注入,注入TestService对象。
public class EighthController : ApiController { private ITestService _ITestService = null; public EighthController(ITestService testService) { this._ITestService = testService; } [HttpGet] public string GetInfor() { var result = _ITestService.GetInfor(); return result; } }
8. 利用PostMan进行测试 http://localhost:2131/api/Eighth/GetInfor, 测试成功。
二. AOP
1. 通过Nuget引入Unity.Interception程序集,同时会自动把它依赖的Unity.Abstractions程序集引入。
PS:【版本:5.5.3】
2. 新增TestService2类和ITestService2接口,用来测试AOP。
代码如下:
1 public interface ITestService2 2 { 3 string GetInfor2(); 4 } 5 public class TestService2 : ITestService2 6 { 7 public string GetInfor2() 8 { 9 return "我是ypf2"; 10 } 11 }
3. 新建AOP文件夹,并新建LogBeforeBehavior类,实现IInterceptionBehavior接口,在Invoke中写AOP相关的代码。
1 ///2 /// Unity为我们提供了一个IInterceptionBehavior接口需要实现这个接口 3 /// 接口为我们提供了三个方式(GetRequiredInterfaces、Invoke、WillExecute)实现 4 /// WillExecute表示是否执行该行为,如果是false这个方法被调用时,不会被捕捉。因为我们总是要执行的,所以为true 5 /// GetRequiredInterfaces将你想要的接口类型和行为联系起来,我们暂时不需要,所以返回Type.EmptyTypes 6 /// Invoke执行方式接口,我们主要使用它 7 /// 8 public class LogBeforeBehavior : IInterceptionBehavior 9 { 10 public bool WillExecute 11 { 12 get { return true; } 13 } 14 15 public IEnumerable GetRequiredInterfaces() 16 { 17 return Type.EmptyTypes; 18 } 19 20 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 21 { 22 Console.WriteLine("我是方法执行前执行的业务"); 23 24 //下面这句话表示这里执行方法 25 var result = getNext()(input, getNext); 26 return result; 27 } 28 }
4. 在UnityConifig.xml文件中配置AOP相关的代码,并且给TestService2注入的代码配置AOP相关的LogAopBehavior类。
代码分享:
12 3 5"unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> 4 6 7 26"Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> 8 9 10 25"apiContainer"> 11 12 24"Interception"/> 13 14 15 18 "WebApiBasic.Interface.ITestService,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService,01-WebApiBasic"/> 19 "WebApiBasic.Interface.ITestService2,01-WebApiBasic" mapTo="WebApiBasic.Service.TestService2,01-WebApiBasic"> 20 23"InterfaceInterceptor"/> 21 "WebApiBasic.AOP.LogBeforeBehavior,01-WebApiBasic"/> 22
5. 用PostMan进行测试 http://localhost:2131/api/Eighth/GetInfor2 ,通过加断点,发现:执行方法前,先进入了LogBeforeBehavior类中进行执行了。
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。