在ASP.NET WebAPI中使用Castle Windsor
1、通过NuGet安装Castle Windsor
2、定义实现 IDependencyResolver 接口的 IocWindsorDependencyResolver 类,作为全局 HttpConfiguration 的 Resolver
public class IocWindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public IocWindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return new IocWindsorDependencyScope(_container);
}
public object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (!_container.Kernel.HasComponent(serviceType))
{
return new object[0];
}
return _container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
3、定义IocWindsorDependencyScope,实现 IDependencyScope
public class IocWindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public IocWindsorDependencyScope(IWindsorContainer container)
{
this._container = container;
this._scope = container.BeginScope();
}
public object GetService(Type serviceType)
{
if (_container.Kernel.HasComponent(serviceType))
{
return _container.Resolve(serviceType);
}
else
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this._container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
this._scope.Dispose();
}
}
4、创建一新 IHttpControllerActivator,更改 Controller 创建方式为从容器 Container 中获取
public class IocWindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public IocWindsorCompositionRoot(IWindsorContainer container)
{
this.container = container;
}
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller = (IHttpController)this.container.Resolve(controllerType);
request.RegisterForDispose(new Release(() => this.container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
this.release();
}
}
}
5、现在需要在Global.asax全局中生成Castle Windsor实例
public class WebApiApplication : System.Web.HttpApplication
{
private static IWindsorContainer _container;
protected void Application_Start()
{
ConfigureWindsor(GlobalConfiguration.Configuration);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(c => WebApiConfig.Register(c, _container));
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// 记录日志
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(Server.MapPath("Log4Net.config")));
}
protected void Application_Error(object sender, EventArgs e)
{
// 返回当前异常
var ex = Server.GetLastError();
// 记录日志信息
Log4netHelper.Error(ex.Message, ex);
}
public static void ConfigureWindsor(HttpConfiguration configuration)
{
_container = new WindsorContainer();
_container.Install(FromAssembly.This());
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
var dependencyResolver = new IocWindsorDependencyResolver(_container);
configuration.DependencyResolver = dependencyResolver;
}
protected void Application_End()
{
_container.Dispose();
base.Dispose();
}
}
6、更改App_Start \ WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config, IWindsorContainer container)
{
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//HttpClient请求内容压缩的支持
config.MessageHandlers.Add(new DecompressionHandler());
RegisterControllerActivator(container);
}
private static void RegisterControllerActivator(IWindsorContainer container)
{
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),
new IocWindsorCompositionRoot(container));
}
}
7、需要告诉Castle Windsor在何种条件下,以怎样的方式注册依赖。Castle Windsor提供了IWindsorInstaller接口。
A、ApiController注册依赖
public class ApiControllersInstaller : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container,
Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<ApiController>()
.LifestylePerWebRequest());
}
}
B、Repository接口注册依赖
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
//container.Register(
// Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>().LifestylePerWebRequest());
Assembly assembly = Assembly.Load("XXX.Repository");
container.Register(Classes.FromAssembly(assembly)
.Where(t => t.Name.EndsWith("Repository"))
.WithServiceDefaultInterfaces()
.Configure(c => c.LifestyleTransient()));
}
}