Castle Windsor ApiController工厂实现ASP.NET Web API

我知道可以使用DependancyResolver并将Castle Windsor注册到MVC但是由于https://stackoverflow.com/a/4889222/139392中描述的问题,我们坚持使用我们的MVC项目上的WindsorControllerFactory实现方法。

然而,看起来ApiControllers正在使用其他类型的工厂,因为Castle Windsor无法注入依赖项。

有没有人想出如何在不使用DependencyResolver的情况下将Castle Windsor与ASP.NET Web API和MVC一起使用?

感谢Critiano的post和一些在线搜索我设法让它在这里工作是其他任何有这个问题的代码。 我已经习惯使用MVC3和ASP.NET Web Api Beta,但我认为同样的解决方案应该适用于MVC4。

首先,我创建了一个WindsorHttpControllerFactory,因为ApiControllers使用的工厂与MVC不同。

public class WindsorHttpControllerFactory : IHttpControllerFactory { private readonly IKernel kernel; private readonly HttpConfiguration configuration; public WindsorHttpControllerFactory(IKernel kernel, HttpConfiguration configuration) { this.kernel = kernel; this.configuration = configuration; } public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName) { if (controllerName == null) { throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", controllerContext.Request.RequestUri.AbsolutePath)); } var controller = kernel.Resolve(controllerName); controllerContext.Controller = controller; controllerContext.ControllerDescriptor = new HttpControllerDescriptor(configuration, controllerName, controller.GetType()); return controllerContext.Controller; } public void ReleaseController(IHttpController controller) { kernel.ReleaseComponent(controller); } } 

棘手的部分是注册它似乎涉及注册一大堆其他东西。 这就是我最终的结果。

 container.Register(Component.For().ImplementedBy().LifeStyle.Singleton); container.Register(Component.For().ImplementedBy().LifeStyle.Singleton); container.Register(Component.For().ImplementedBy().LifeStyle.Singleton); container.Register(Component.For().ImplementedBy().LifeStyle.Transient); container.Register(Component.For().ImplementedBy().LifeStyle.Transient); container.Register(Component.For().ImplementedBy().LifeStyle.Transient); container.Register(Component.For().ImplementedBy().LifeStyle.Transient); container.Register(Component.For().ImplementedBy().LifeStyle.Transient); container.Register(Component.For().Instance(configuration)); //Register all api controllers container.Register(AllTypes.FromAssembly(assemblyToRegister) .BasedOn() .Configure(registration => registration.Named(registration.ServiceType.Name.ToLower().Replace("controller", "")).LifeStyle.Transient)); //Register WindsorHttpControllerFactory with Service resolver GlobalConfiguration.Configuration.ServiceResolver.SetService(typeof(IHttpControllerFactory), container.Resolve()); 

我必须创建我自己的ILogger实现,你可以使用像波纹管那样的存根版本。

 public class MyLogger : System.Web.Http.Common.ILogger { public void LogException(string category, TraceLevel level, Exception exception) { // Do some logging here eg. you could use log4net } public void Log(string category, TraceLevel level, Func messageCallback) { // Do some logging here eg. you could use log4net } } 

两天前我也遇到过这个问题,这篇文章对我有所帮助。 并且不要忘记在Windsor引导程序中添加WebAPI控制器。

 container.Register(AllTypes.FromThisAssembly().BasedOn().LifestyleTransient()); 

ASP.NET MVC 4 RC的更新:这个有用的post告诉你如何使用Windsor和WebAPI,它就像一个魅力。

看看这篇文章

我没有切换到包括web.api在内的mvc 4 beta(我还在使用WCF web api Prev6),但是线程中已经指出的方式似乎要走了

我写了一篇关于如何做到这一点的post,并将它连接到RavenDB,你可能会发现这里有用

我已经设法通过使用GlobalConfiguration.Configuration.ServiceResolver.SetResolver从我的windsor容器中解析,如下所示。

Windsor Code示例

 private void BootStrapWindsorContainer() { _container = new WindsorContainer() .Install(FromAssembly.This()); var controllerFactory = new WindsorControllerFactory(_container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory); ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(_container)); GlobalConfiguration.Configuration.ServiceResolver.SetResolver( t => { try { return _container.Resolve(t); } catch { return null; } }, t => { try { return _container.ResolveAll(t).OfType(); } catch { return new List(); } }); } 

当你无法解析类型时返回null工作,似乎MVC将新建依赖项。

编辑:确保您有IHttpController的安装程序

 public class WindsorHttpControllerFactory : IHttpControllerActivator { readonly IWindsorContainer _container; public WindsorHttpControllerFactory(IWindsorContainer container) { _container = container; } public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { var controller = (IHttpController)_container.Resolve(controllerType); request.RegisterForDispose(new Release(() => _container.Release(controller))); return controller; } class Release : IDisposable { readonly Action _release; public Release(Action release) { _release = release; } public void Dispose() { _release(); } } }