IoC实践--ASP.NET MVC5 采用Unity依赖注入Filter详解

转载自:  http://www.lanhusoft.com/Article/111.html

 

最近写了两篇关于ASP.NET mvc5 采用Unity依赖注入的 文章,前面两篇分别是对Controller和View,这次介绍一下:ASP.NET MVC5 采用Unity成功依赖注入Filter,对Filter的IoC稍微复杂一些。我通过对一个写日志的Filter里面的一个接口进行依赖注入,使用 了.net中的Atrribute特性技术和Filter的AOP技术,下面具体的详细步骤。

1、记日志组件接口

  1. namespace MVC5DependencyInjection.Abstract
  2. {
  3. public interface ILogService
  4. {
  5. void Write(string msg);
  6. }
  7. }

2、记文本文件日志组件具体类

  1. using MVC5DependencyInjection.Abstract;
  2. using System;
  3. using System.IO;
  4. namespace MVC5DependencyInjection.Concrete
  5. {
  6. public class TextLogService : ILogService
  7. {
  8. public void Write(string msg)
  9. {
  10. string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Log\");
  11. if (!Directory.Exists(logDir))
  12. {
  13. Directory.CreateDirectory(logDir);
  14. }
  15. string fileName = DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
  16. using (StreamWriter sw = new StreamWriter(logDir + fileName, true))
  17. {
  18. sw.WriteLine(DateTime.Now.ToString() + ":" + msg);
  19. sw.WriteLine("---------------------------------------------------------");
  20. sw.Close();
  21. }
  22. }
  23. }
  24. }

这类就是负责记录信息到文本文件,日志文件放根目录的Log目录下面,一天一个文件。

3、声明一个调用日志组件的Action Filter过滤器

  1. using Microsoft.Practices.Unity;
  2. using MVC5DependencyInjection.Abstract;
  3. using System;
  4. using System.Diagnostics;
  5. using System.Web.Mvc;
  6. namespace MVC5DependencyInjection.Filters
  7. {
  8. public class LogActionFilter : FilterAttribute,IActionFilter
  9. {
  10. private ILogService logService;
  11. private Stopwatch timer;
  12. [Dependency]
  13. public ILogService LogService
  14. {
  15. get { return logService; }
  16. set { logService = value; }
  17. }
  18. //public LogActionFilter(ILogService log)
  19. //{
  20. // this.logService = log;
  21. //}
  22. public void OnActionExecuting(ActionExecutingContext filterContext)
  23. {
  24. timer = Stopwatch.StartNew();
  25. logService.Write(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
  26. + ",客户请求:"
  27. + filterContext.HttpContext.Request.RawUrl + ",开始");
  28. }
  29. public void OnActionExecuted(ActionExecutedContext filterContext)
  30. {
  31. timer.Stop();
  32. logService.Write(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
  33. + ",客户请求:"
  34. + filterContext.HttpContext.Request.RawUrl + ",结束,耗时:" + timer.Elapsed.TotalSeconds + "秒");
  35. }
  36. }
  37. }

这里自定义的ActionFilter过滤器主要是用一个Stopwatch监测客户 请求响应时间。这个类是继承于特性类FilterAttribute和接口IActionFilter。FilterAttribute是为了可以用特性 的形式用于某些Controller和Action。OnActionExecuting是要监测Action执行之前的方 法,OnActionExecuted是要监测Action执行之前后的方法,这两个方法的参数都是ActionExecutedContext类型,这 个参数可以获取请求相关的信息,其中就包括请求上下文HttpContext。

注意: 属性为LogService加了特性Dependency,标示可以通过Unity注入;这里是定义采用的属性的形式,而不是采用构造函数,因为这是定义是一个特性Filter,如果采用构造函数在使用的比较麻烦,要传参数。

4、应用Filter到Action

这里用我这前写的IoC实践--ASP.NET MVC5 采用Unity依赖注入View详解里面的Controller,在Show的Action方法前面加上 前面定义好的Filter,加上[LogActionFilter]。

  1. public class UserController : Controller
  2. {
  3. private IUser service;
  4. public UserController(IUser service)
  5. {
  6. this.service = service;
  7. }
  8. public ActionResult Index()
  9. {
  10. var data = this.service.GetUsers();
  11. return View(data);
  12. }
  13. [LogActionFilter]
  14. public ActionResult Show()
  15. {
  16. return View();
  17. }
  18. }

5、新加一个FilterProvider使用Unity对Filter进行依赖注入

  1. using Microsoft.Practices.Unity;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Web.Mvc;
  5. namespace MVC5DependencyInjection.Filters
  6. {
  7. public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider
  8. {
  9. private readonly IUnityContainer container;
  10. public UnityFilterAttributeFilterProvider(IUnityContainer container)
  11. {
  12. this.container = container;
  13. }
  14. protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
  15. {
  16. var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
  17. this.BuildUpAttributes(attributes);
  18. return attributes;
  19. }
  20. protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
  21. {
  22. var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
  23. this.BuildUpAttributes(attributes);
  24. return attributes;
  25. }
  26. private void BuildUpAttributes(IEnumerable attributes)
  27. {
  28. foreach (FilterAttribute attribute in attributes)
  29. {
  30. container.BuildUp(attribute.GetType(), attribute);
  31. }
  32. }
  33. }
  34. }

我们继承FilterAttributeFilterProvider类,重写 了 GetControllerAttributes和GetActionAttributes方法。用传构造函数传入的UnityContainer对 象对指定到Action或Controller的特性进行依赖注入。

6、注册依赖使用依赖注入生效

  1. using Microsoft.Practices.Unity;
  2. using MVC5DependencyInjection.Abstract;
  3. using MVC5DependencyInjection.Concrete;
  4. using MVC5DependencyInjection.Filters;
  5. using System.linq;
  6. using System.Web.Mvc;
  7. using System.Web.Optimization;
  8. using System.Web.Routing;
  9. using Unity.Mvc4;
  10. namespace MVC5DependencyInjection
  11. {
  12. public class MvcApplication : System.Web.HttpApplication
  13. {
  14. protected void Application_Start()
  15. {
  16. AreaRegistration.RegisterAllAreas();
  17. FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  18. RouteConfig.RegisterRoutes(RouteTable.Routes);
  19. BundleConfig.RegisterBundles(BundleTable.Bundles);
  20. Initialise();
  21. }
  22. IUnityContainer BuildUnityContainer()
  23. {
  24. var container = new UnityContainer();
  25. container.RegisterType<IUser, SimpleUser>();
  26. container.RegisterInstance<IMessageService>(new MessageService
  27. {
  28. Message = "欢迎你来到wwww.lanhusoft.com",
  29. ImageUrl = "/Content/Images/1.jpg"
  30. });
  31. container.RegisterType<ILogService, TextLogService>();
  32. container.RegisterInstance<IFilterProvider>("FilterProvider", new UnityFilterAttributeFilterProvider(container));
  33. return container;
  34. }
  35. void Initialise()
  36. {
  37. var container = BuildUnityContainer();
  38. DependencyResolver.SetResolver(new UnityDependencyResolver(container));
  39. }
  40. }
  41. }
container.RegisterInstance<IFilterProvider>("FilterProvider", new UnityFilterAttributeFilterProvider(container)); 

这行代码表示将我们自定义的UnityFilterAttributeFilterProvider绑定到内置的mvc框架里面去,使Filter能够依赖注入。

7、运行页面查看结果


8、总结

本例虽然是用到Unity对filter进行依赖注入,其实主要理解这里面的核心思想,换成Ninject、Autofac、StructureMap对 Filter依赖注入也很容易。因为这里面的主要用到的是要自定义实现一个IFilterProvider,在用FilterProvider里面调用 IoC容器的API对Filter所依赖进行注入对象。
用Ninject对对Filter依赖注入可以参考:

http://odetocode.com/blogs/scott/archive/2011/01/20/injectable-configurable-action-filters.aspx


本站文章除注明转载外,均为本站原创或翻译,欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,共创和谐网络环境。
转载请注明:文章转载自:蓝狐软件工作室 » IoC实践--ASP.NET MVC5 采用Unity依赖注入Filter详解
本文标题:IoC实践--ASP.NET MVC5 采用Unity依赖注入Filter详解
本文地址:http://www.lanhusoft.com/Article/111.html
posted @ 2015-08-17 16:14  清幽紫竹  Views(763)  Comments(0)    收藏  举报