StructureMap依赖注入

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也是一样的。这样就充分的降低了代码之间的耦合度。

原文地址:https://www.cnblogs.com/jobs2/p/3211334.html