一直想写一篇关于unity 详细的配置信息的文章,也算是自我总结吧
先介绍了unity , Unity是微软官方推荐使用的轻型的IOC框架,支持各种方式的注入 ,使用来解耦的利器.
获取unity 的方式呢你可以直接下载对应的dll文件或者去对应的网站下载,我个人推荐呢用NuGet直接添加和管理.
添加方式如下图
安装之后呢会自动添加到项目里,当有更新的时候,直接在窗口里面更新就行,或者执行命令行 Update-Package Mvc{tab}
,如果你只需要注入普通的MVC的话那现在啊就可以了。但是如果你可能还需要注入webapi的话那么你就还需要引入这个库
磨刀不误砍柴工,包准备好了现在可以开始配置了,
总的来说unity的配置分为3步
1:填写配置文件指定映射关系
2:创建容器载入配置文件
3:构造注入或者属性注入。
完成了这几步呢就可以开始使用了
先说配置文件吧。先发个图看看完整的结构
其实看这很负责用起来的话不是这样,如果你只是简单来用的话其实就只需要关注5个节点
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<alias alias="IClass" type="IservicesVc.test, IservicesVc" />
<alias alias="MyClass" type="Services.test, Services" />
<namespace name="IservicesVc.test" />
<namespace name="Services.test" />
<assembly name="IservicesVc" />
<assembly name="Services" />
<container>
<register type="Itesttwo" mapTo="testtwo" />
<register type="ITestIoc" mapTo="TestIo" />
</container>
</unity>
</configuration>
从上往下看呢首先<alias>节点用来指定程序集之间的映射关系 alias是表示节点的别名,type是指定类型用的 "结构为命名空间+文件名,命名空间",,<namespace>用来指定引用程序集的命名空间 name属性=命名空间+文件夹名称(如果是多个映射),<assembly > name="程序命名空间" 用来指定引用的程序集
<container> 就是容器节点了。里面的<register>节点用来用的类之间的映射关系,type="需要映射的类型",mapto="映射的目标类型" 下面贴下对应的代码
namespace IservicesVc.test
{
public interface ITestIoc
{
int sum(int sumone, int sumtwo);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IservicesVc.test { public interface Itesttwo { int count(int i, int j); } }
using IservicesVc.test;
namespace Services.test
{
public class TestIo :ITestIoc
{
public int sum(int sumone, int sumtwo)
{
return sumone + sumtwo;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IservicesVc.test; using Microsoft.Practices.Unity; namespace Services.test { public class testtwo:Itesttwo { [Dependency] public ITestIoc ii { get; set; } public int count(int i, int j) { var sum = ii.sum(i,j); return sum * sum; } } }
配置完成后呢。就是需要开始注册了。
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 TestUnityIocVC.App_Start; namespace TestUnityIocVC { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); //注入方法 Bootstrapper.Initialise(); } } }
重点是Bootstrapper.Initialise();方法
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Http; using System.Web.Mvc; using IservicesVc.test; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.Configuration; using Services.test; using Unity.WebApi; namespace TestUnityIocVC.App_Start { public static class Bootstrapper { public static void Initialise() { //UnityContainer container = new UnityContainer(); //UnityConfigurationSection configuration = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection; //configuration.Configure(container, "defaultContainer"); var container = BuildUnityContainer(); DependencyResolver.SetResolver(new UnityDependencyResolver(container));//MVC注入 //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);//MVC GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);//WebAPi注入 } /// <summary> /// Builds the unity container. /// </summary> /// <returns></returns> private static IUnityContainer BuildUnityContainer() { var container = new UnityContainer(); //container.RegisterType<INodeBiz, NodeBiz>(); var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = HttpContext.Current.Server.MapPath("~/Unity.config") }; Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); var unitySection = (UnityConfigurationSection)configuration.GetSection("unity"); container.LoadConfiguration(unitySection); //container.RegisterType<ITestIoc, TestIo>(); return container; } } }
通过BuildUnityContainer方法构造容器, 容器的结构是从配置文件的读取的,但是现在你如果运行会报错为什么呢,因为你如果需要MVC注入的话还需要一些别的处理.
我们要实现MVC3中新提供 的两个接口:IDependencyResolver和IControllerActivator
IDependencyResolver公开两个方法 - GetService的GetServices.The GetService方法解决了单独注册的服务,支持任意对象的创建,GetServices解决注册多个服务。IDependencyResolver接口的实现应该委托给底层的依赖注入容器提供注册服务请求的类型。当有没有注册的服务请求的类型,ASP.NET MVC框架预计这个接口的实现返回GetService为空,并从GetServices返回空集合。让我们以统一提供依赖注入工作IDependencyResolver intreface派生创建一个自定义的依赖解析器类。
我们定义一个类名为UnityDependencyResolver:
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
namespace TestUnityIocVC
{
public class UnityDependencyResolver : IDependencyResolver { IUnityContainer container; public UnityDependencyResolver(IUnityContainer container) { this.container = container; } public object GetService(Type serviceType) { try { return container.Resolve(serviceType); } catch { return null; } } public IEnumerable<object> GetServices(Type serviceType) { try { return container.ResolveAll(serviceType); } catch { return new List<object>(); } } } }
实现两个方法GetService和GetServices。使用Unity容器返回我们需要的Service或者ojbect。
实现两个方法GetService和GetServices。使用Unity容器返回我们需要的Service或者ojbect。
ASP.NET MVC 3以后的版本已经推出了一个新的接口IControllerActivator,让您激活与自定义的行为控制器,并且可以使用依赖注入.让我们创建一个派生自IControllerActivator 接口的一个自定义的控制器
Icontroller
using System;
using System.Web.Mvc;
namespace TestUnityIocVC
{
public class CustomControllerActivator : IControllerActivator
{
IController IControllerActivator.Create(System.Web.Routing.RequestContext requestContext,
Type controllerType)
{
return DependencyResolver.Current
.GetService(controllerType) as IController; } } }
到这。整个注册就完成了
那么在MVC 的控制器和webapi中就可以用了
(MVC)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using IservicesVc; using IservicesVc.test; using Microsoft.Practices.Unity; using Services.test; namespace TestUnityIocVC.Controllers { public class HomeController : Controller { //属性注入; [Dependency] public ITestIoc _TestIoc { get; set; } public Itesttwo test = DependencyResolver.Current.GetService<Itesttwo>(); //private readonly ITestIoc _testIoc; //public HomeController(ITestIoc testIoc) //{ // _testIoc = testIoc; //} public ActionResult Index() { var count = _TestIoc.sum(10, 20); ViewBag.Title = "home"; return View(); } } }
(WEBapi)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http; using IservicesVc.test; namespace TestUnityIocVC.Controllers.Api { public class testController : ApiController { private readonly Itesttwo _testIoc; public testController(Itesttwo testIoc) { _testIoc = testIoc; } public IEnumerable<string> Get() { var sum = _testIoc.count(10, 20); return new string[] { "value1", sum.ToString() }; } } }