StructureMap依赖注入
2013-07-24 18:05 呆河马 阅读(1711) 评论(3) 编辑 收藏 举报IOC:控制反转,是一种设计模式。一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制;第二层是依赖注入:将相互依赖的对象分离,在spring配置文件中描述他们的依赖关系。他们的依赖关系只在使用的时候才建立。
AOP:面向切面,是一种编程思想,OOP的延续。将系统中非核心的业务提取出来,进行单独处理。比如事务、日志和安全等。
一.配置与注册Services和Repositories
首先我们告诉StructureMap,我们需要注入的是什么,本系统中需要注册的是Services和Repositories,分别注入到 Controller和Service。下面是具体写法,为什么这么写,不必较真,写法是StructureMap提供给我们的,使用就好了。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using StructureMap; namespace TYStudioDemo.StructureMap { public class BootStrapper { public static void ConfigureStructureMap() { ObjectFactory.Configure(x => { x.AddRegistry(new TYStudioDemoStructureMapRegistry()); x.Scan(scanner => { scanner.Assembly("TYStudioDemo.Services"); scanner.Assembly("TYStudioDemo.Repositories"); }); }); } } }
上面的代码告诉了StructureMap去哪里找我们的Service和Repositories。同时 TYStudioDemoStructureMapRegistry这个类告诉了StructureMap该用哪个类去实例化我们的接口,下面是 TYStudioDemoStructureMapRegistry的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using StructureMap.Configuration.DSL; using TYStudioDemo.Models; using TYStudioDemo.DTO; using TYStudioDemo.Interfaces; using TYStudioDemo.Services; using TYStudioDemo.Repositories; namespace TYStudioDemo.StructureMap { public class TYStudioDemoStructureMapRegistry : Registry { //注册接口实际使用的实现类 public TYStudioDemoStructureMapRegistry() { SelectConstructor<TYEntities>(() => new TYEntities()); //Exception Handle For<ITYExceptionService>().Use<TYExceptionService>(); //Services For(typeof(ISupplierService)).Use(typeof(SupplierService)); //Repositories For(typeof(ISupplierRepository<>)).Use(typeof(SupplierRepository)); For(typeof(IProductRepository<>)).Use(typeof(ProductRepository)); } } }
现在我们已经配置了StructureMap并且注册了Service和Repository,接下来该告诉系统去使用StructureMap去实例化我们的Controller。
二.创建Controller Factory
既然使用了依赖注入,Controller的实例化当然不能再用系统本身的了,所以我们需要创建一个ControllerFactory:TYStudioDemoStructureMapControllerFactory。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web.Mvc; using StructureMap; namespace TYStudioDemo.StructureMap { public class TYStudioDemoStructureMapControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, System.Type controllerType) { if (controllerType != null) { Controller c = ObjectFactory.GetInstance(controllerType) as Controller; //当返回一个错误页面,View一级异常会被触发 c.ActionInvoker = new ErrorHandlingActionInvoker(new HandleErrorAttribute()); return c; } else return null; } } }
TYStudioDemoStructureMapControllerFactory继承自 DefaultControllerFactory,DefaultControllerFactory是MVC默认的Controller Factory,然后重新器获得Controller实例的方法,由StructureMap的ObjectFactory来创建实 例,StructureMap会帮我们把Controller构造函数中的参数实例化。 上面的ErrorHandlingActionInvoker方法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; namespace TYStudioDemo.StructureMap { public class ErrorHandlingActionInvoker : ControllerActionInvoker { private readonly IExceptionFilter filter; public ErrorHandlingActionInvoker(IExceptionFilter filter) { if (filter == null) throw new ArgumentNullException("Exception filter is missing"); this.filter = filter; } protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDes criptor actionDes criptor) { var filterInfo = base.GetFilters(controllerContext, actionDes criptor); filterInfo.ExceptionFilters.Add(this.filter); return filterInfo; } } }
Controller Factory创建ok。但是这样系统是不会使用我们自己的Controller Factory的,所以需要通知一下MVC系统。
三.配置Global.asax文件
在Application_Start()方法中也就是项目启动的时候注册StructureMap并通知系统使用我们自己的Controller Factory进行实例化Controller。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using TYStudioDemo.StructureMap; namespace TYStudioDemo.WebUI { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); AuthConfig.RegisterAuth(); //注册StructureMap BootStrapper.ConfigureStructureMap(); //通过StructureMap返回Controller实例,通过构造器注入 ControllerBuilder.Current.SetControllerFactory(new TYStudioDemoStructureMapControllerFactory()); } protected void Application_EndRequest(object sender, EventArgs e) { TYStudioDemo.Models.TYEntities.Cleanup(); } } }
ok,到此StructureMap的配置就全部完成了,接下来我们该怎么使用它呢。 文章开头已经告诉大家了我们使用Constructor构造器的方式进行依赖注入。 Controller的写法 既然是构造器就要写构造函数了,见下面写法:
ISupplierService _supplierService; public SupplierController(ITYExceptionService tyExceptionService, ISupplierService supplierService) { _tyExceptionService = tyExceptionService; _supplierService = supplierService; }
在构造方法中加入我们要注入的Service接口,然后StructureMap就会根据上面TYStudioDemoStructureMapRegistry的配置去创建我们需要实例化的service对象了。 同样向Service中注入Repository的写法是一样的:
ISupplierRepository<Supplier> _supplierRepository; IProductRepository<Product> _productRepository; public SupplierService(ISupplierRepository<Supplier> supplierRepotitory, IProductRepository<Product> productRepository) { _supplierRepository = supplierRepotitory; _productRepository = productRepository; }
至此StructureMap配置与使用就全部完成了。
总结:
我们发现,我们的参数都是接口类型了,这样的好处就是将来对ISupplierService的实现不一样了,我们只需要重写写一个 ISupplierService的实现了,并修改TYStudioDemoStructureMapRegistry使 ISupplierService使用新的实现类,就可以了。因为我们使用的都是接口所以方法和参数都是固定的,所以呢~~ Controller中不用修改任何代码,同理Service也是一样的。这样就充分的降低了代码之间的耦合度。