今天主要来讲解使用Unity来自动注入。Unity前面我们已经详细的介绍过了,如有需要请自行前往去看,今天我们的重点是说MVC与IOC的结合。
IOC:控制反转,控制反转的工具是DI(依赖注入:构造函数注入--属性注入--方法注入(按时间顺序)),DI使用的工具是Unity容器。
一:新增mvc项目,然后nuget添加引用
1 <package id="Unity" version="5.10.3" targetFramework="net45" /> 2 <package id="Unity.Abstractions" version="4.1.3" targetFramework="net45" /> 3 <package id="Unity.Configuration" version="5.10.0" targetFramework="net45" /> 4 <package id="Unity.Container" version="5.10.3" targetFramework="net45" /> 5 <package id="Unity.Interception" version="5.10.1" targetFramework="net45" /> 6 <package id="Unity.Interception.Configuration" version="5.10.0" targetFramework="net45" />
二:新增文件夹CfgFiles新增一个unity.config文件,具体代码和注释如下:
1 <configuration> 2 <configSections> 3 <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> 4 </configSections> 5 <unity> 6 <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> 7 <containers> 8 <container name="ruanmouContainer"> 9 <extension type="Interception"/> 10 <!--<register type="命名空间.接口类型2,程序集" mapTo="命名空间.实现类型2,程序集" />--> 11 <register type="System.Data.Entity.DbContext, EntityFramework" mapTo="Ruanmou.EF.Model.JDDbContext, Ruanmou.EF.Model"/> 12 13 <register type="Ruanmou.Bussiness.Interface.IUserCompanyService,Ruanmou.Bussiness.Interface" mapTo="Ruanmou.Bussiness.Service.UserCompanyService, Ruanmou.Bussiness.Service"> 14 <interceptor type="InterfaceInterceptor"/> 15 </register> 16 17 <register type="Ruanmou.Bussiness.Interface.IUserService,Ruanmou.Bussiness.Interface" mapTo="Ruanmou.Bussiness.Service.UserService, Ruanmou.Bussiness.Service"> 18 <interceptor type="InterfaceInterceptor"/> 19 <interceptionBehavior type="Ruanmou.Project.AOP.LogBeforeBehavior, Ruanmou.MVC5"/> 20 <interceptionBehavior type="Ruanmou.Project.AOP.LogAfterBehavior, Ruanmou.MVC5"/> 21 </register> 22 23 <register type="Ruanmou.Bussiness.Interface.ICompanyService,Ruanmou.Bussiness.Interface" mapTo="Ruanmou.Bussiness.Service.CompanyService, Ruanmou.Bussiness.Service"> 24 <interceptor type="InterfaceInterceptor"/> 25 </register> 26 </container> 27 </containers> 28 </unity> 29 </configuration>
需要注意的是:
1:一定在unity.config的属性中设置:复制到输出目录一定要设置:始终复制,这样做的目的是每次重新生成,会把这个untiy.config文件copy到bin目录下面。保证每次都是使用的是最新的。
2:下面这两个类是AOP拦截器需要的,如果需要的话则新增这些实体类,不需要的则直接删除掉。
<interceptionBehavior type="Ruanmou.Project.AOP.LogBeforeBehavior, Ruanmou.MVC5"/>
<interceptionBehavior type="Ruanmou.Project.AOP.LogAfterBehavior, Ruanmou.MVC5"/>
三:新增读取unity.config配置文件类DIFactory,代码如下:
1 public class DIFactory 2 { 3 private static IUnityContainer container = null; 4 static DIFactory() 5 { 6 ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); 7 fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\Unity.Config"); 8 Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); 9 UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); 10 container = new UnityContainer(); 11 section.Configure(container, "ruanmouContainer"); 12 } 13 14 public static IUnityContainer GetContainer() 15 { 16 return container; 17 } 18 }
四:新增defaultController类的子类DIControllerFactory来进行重新,具体代码如下:
1 public class DIControllerFactory : DefaultControllerFactory 2 { 3 private Logger logger = new Logger(typeof(DIControllerFactory)); 4 5 protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 6 { 7 this.logger.Warn($"{controllerType.Name}被构造..."); 8 9 IUnityContainer container = DIFactory.GetContainer(); 10 //return base.GetControllerInstance(requestContext, controllerType); 11 return (IController)container.Resolve(controllerType); 12 } 13 }
五:在Global.asax中指定控制器为当前新增的控制器DIControllerFactory,代码如下:
1 public class MvcApplication : System.Web.HttpApplication 2 { 3 private Logger logger = new Logger(typeof(MvcApplication)); 4 protected void Application_Start() 5 { 6 7 AreaRegistration.RegisterAllAreas();//注册区域 8 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//注册全局的Filter 9 RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由 10 BundleConfig.RegisterBundles(BundleTable.Bundles);//合并压缩 ,打包工具 Combres 11 12 ControllerBuilder.Current.SetControllerFactory(new DIControllerFactory()); 13 14 this.logger.Info("网站启动了。。。"); 15 } 16 }
六:上面的准备工作已经做好了,下面来测试使用:
1 public class ThirdController : Controller 2 { 3 private IUserService _iUserService = null; 4 private ICompanyService _iCompanyService = null; 5 private IUserCompanyService _iUserCompanyService = null; 6 /// <summary> 7 /// 构造函数注入---控制器得是由容器来实例化 8 /// </summary> 9 /// <param name="userService"></param> 10 /// <param name="companyService"></param> 11 /// <param name="userCompanyService"></param> 12 public ThirdController(IUserService userService, ICompanyService companyService, IUserCompanyService userCompanyService) 13 { 14 this._iUserService = userService; 15 this._iCompanyService = companyService; 16 this._iUserCompanyService = userCompanyService; 17 18 19 } 20 21 22 // GET: Third 23 public ActionResult Index() 24 { 25 IUserService service = this._iUserService; 26 User user = service.Find<User>(2); 27 return View(); 28 } 29 }
通过以上6个步骤则完成了IOC与MVC的完美结合,以后不用每次在new 一个业务类了。可以在初始化控制器的时候进行初始化那些业务类。