WebApi 整合IOC Unity
新建接口文件IUserService:
namespace SOA.Interface
{
public interface IUserService
{
string Query();
}
}
新建实现类文件UserService:
namespace SOA.Service
{
public class UserService : IUserService
{
public string Query()
{
return JsonConvert.SerializeObject(new {
Id=123,
Name ="陈贺章",
Description = "VIP用户"
});
}
}
}
小白
新建控制器UserController,最简单最常规的方式就是实例化类调用方法:
namespace SOA.WebApi.Controllers
{
public class UserController : ApiController
{
public string GetUser()
{
IUserService service = new UserService();
return service.Query();
}
}
}
高手
因为我们这里用到了接口IUserService,所以我们最好能通过容器实现,.net 最常用的就是Unity
引入Unity所需程序包:Unity、Unity.Interception、Unity.Abstractions、Unity.Interception.Configuration、Unity.WebApi
新建配置文件 /CfgFiles/Unity.Config
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<unity>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
<containers>
<container name="webApiContainer">
<!--SOA.Interface.IUserService 指向 SOA.Service.UserService-->
<register type="SOA.Interface.IUserService,SOA.Interface" mapTo="SOA.Service.UserService, SOA.Service"/>
</container>
</containers>
</unity>
</configuration>
新建 /Utility/ContainerFactory(简单工厂+配置文件+反射),读取配置文件初始化容器:
namespace SOA.WebApi.Utility
{
public class ContainerFactory
{
private static IUnityContainer _UnityContainer = null;
/// <summary>
/// 通过静态构造函数初始化Unity容器
/// 执行且只执行一次
/// </summary>
static ContainerFactory()
{
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "webApiContainer"); //读取配置文件中的“webApiContainer”,不能乱写
_UnityContainer = container;
}
public static IUnityContainer BuildContainer()
{
return _UnityContainer;
}
}
}
经过这两个步骤之后,我们就能很轻松获取到容器了,相对应的我们可以修改一下Controller查看下效果:
namespace SOA.WebApi.Controllers
{
public class UserController : ApiController
{
public string GetUser()
{
//IUserService service = new UserService();
//return service.Query();
//获取容器
var container = ContainerFactory.BuildContainer();
IUserService service = container.Resolve<IUserService>(); //需要引入using Unity
return service.Query();
}
}
}
效果:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"Id":123,"Name":"陈贺章","Description":"VIP用户"}</string>
大神
尽管我们使用的静态构造,但是每次都需要找容器,因此我们可以使用构造函数注入:
namespace SOA.WebApi.Controllers
{
public class UserController : ApiController
{
private IUserService _IUserService = null;
//构造函数注入
public UserController(IUserService service) {
_IUserService = service;
}
public string GetUser()
{
return _IUserService.Query();
}
}
}
但是这样直接启动访问会报错,因为控制器是由控制器默认工厂创建,增加了带参数的构造函数以后,默认的控制器工厂无法创建控制器,所以可以让Unity来创建控制
自定义 DependencyResolver 继承自 IDependencyResolver接口,实现接口:
namespace SOA.WebApi.Utility
{
public class CustomDependencyResolver : IDependencyResolver
{
private static IUnityContainer unityContainer = null;
static CustomDependencyResolver()
{
unityContainer= ContainerFactory.BuildContainer();
}
/// <summary>
/// 创建一个子容器(指定作用域时)
/// </summary>
/// <returns></returns>
public IDependencyScope BeginScope()
{
return new UnityDependencyResolver(unityContainer.CreateChildContainer());
}
public void Dispose()
{
this.Dispose();
}
public object GetService(Type serviceType)
{
//获取创建的实例,因为不是所有东西都通过IOC注入了(会包含一些系统自带的东西),所以需要try catch,返回null
try
{
return unityContainer.Resolve(serviceType);
}
catch (Exception ex)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
//获取创建的实例,因为不是所有东西都通过IOC注入了(会包含一些系统自带的东西),所以需要try catch,返回null
try
{
return unityContainer.ResolveAll(serviceType);
}
catch (Exception ex)
{
return null;
}
}
}
}
修改WebApiConfig 文件,替换系统框架中的工厂:
config.DependencyResolver = new CustomDependencyResolver(); //替换系统框架中的工厂
//config.DependencyResolver = new UnityDependencyResolver(ContainerFactory.BuildContainer());