【问题标题】:Can't instantiate Controller with Castle using webapi as well也无法使用 webapi 用 Castle 实例化控制器
【发布时间】:2014-12-17 00:09:40
【问题描述】:

我正在一个项目中使用 ApiControllers 和 Controllers(不是 webapi)和 Castle(来自 Nuget)

 internal class WebWindsorInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component
                .For<RepositoryFactories>()
                .ImplementedBy<RepositoryFactories>()
                .LifestyleSingleton());

            container.Register(Component
                .For<IRepositoryProvider>()
                .ImplementedBy<RepositoryProvider>()
                .LifestylePerWebRequest());

            container.Register(Component
                .For<IProjUow>()
                .ImplementedBy<ProjUow>()
                .LifestylePerWebRequest());

            container.Register(Classes
                .FromAssemblyContaining<Api.CategoriesController>()
                .BasedOn<IHttpController>()
                .If(t => t.Name.EndsWith("Controller"))
                .LifestylePerWebRequest());

            container.Register(Classes
                .FromAssemblyContaining<CategoriesController>()
                .BasedOn<IController>()
                .If(t => t.Name.EndsWith("Controller"))
                .LifestylePerWebRequest());
        }
    }

这在 global.asax (Application_Start) 中

var container = new WindsorContainer().Install(new WebWindsorInstaller());
GlobalConfiguration.Configuration.DependencyResolver = new WindsorDependencyResolver(container);

这是 CategoriesController 的 Controller 构造函数

public class CategoriesController : ControllerBase
{
    public CategoriesController(IProjUow uow)
    {
        Uow = uow;
    }
}

并且ControllerBase继承自Controller

ApiController 定义如下:

public abstract class ApiControllerBase : ApiController
{
    protected IProjUow Uow { get; set; }
}

public class CategoriesController : ApiControllerBase
{
    public CategoriesController(IProjUow uow)
    {
        Uow = uow;
    }
}

ApiController 工作正常,但另一个说:

没有为此对象定义无参数构造函数。

为什么?

提前致谢!吉列尔莫。

【问题讨论】:

标签: c# asp.net-mvc asp.net-web-api castle-windsor castle


【解决方案1】:

好的,Phil 的链接为我指明了正确的方向。如果有人遇到同样的问题,我会分享我的解决方案。

这应该在 Global.asax.cx(Application_Start 方法)中

// Set the dependency resolver for Web API.
var webApicontainer = new WindsorContainer().Install(new WebWindsorInstaller());
GlobalConfiguration.Configuration.DependencyResolver = new WebApiWindsorDependencyResolver(webApicontainer);

// Set the dependency resolver for Mvc Controllers
Container = new WindsorContainer()
    .Install(new ControllersInstaller());
DependencyResolver.SetResolver(new MvcWindsorDependencyResolver(Container)); 
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(Container)); 
var controllerFactory = new WindsorControllerFactory(Container.Kernel); 
ControllerBuilder.Current.SetControllerFactory(controllerFactory); 

WebApiWindsorDependecyResolver

 internal class WebApiWindsorDependencyResolver : IDependencyResolver
    {
        private readonly IWindsorContainer container;

        public WebApiWindsorDependencyResolver(IWindsorContainer container)
        {
            if (container == null) { throw new ArgumentNullException("container"); }
            this.container = container;
        }

        public object GetService(Type t)
        {
            return this.container.Kernel.HasComponent(t) ? this.container.Resolve(t) : null;
        }

        public IEnumerable<object> GetServices(Type t)
        {
            return this.container.ResolveAll(t).Cast<object>().ToArray();
        }

        public IDependencyScope BeginScope()
        {
            return new ReleasingDependencyScope(this as IDependencyScope, this.container.Release);
        }

        public void Dispose()
        {
        }
    }

MvcWindsorDependencyResolver

 internal class MvcWindsorDependencyResolver : IDependencyResolver
    {
        private readonly IWindsorContainer container;

        public MvcWindsorDependencyResolver(IWindsorContainer container)
        {
            this.container = container;
        }

        public object GetService(Type serviceType)
        {
            return container.Kernel.HasComponent(serviceType) ? container.Resolve(serviceType) : null;
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return container.Kernel.HasComponent(serviceType) ? container.ResolveAll(serviceType).Cast<object>() : new object[] { };
        }
    }

控制器安装程序

public class ControllersInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(FindControllers().Configure(c => c.LifestyleTransient()));

            container.Register(Component
                .For<RepositoryFactories>()
                .ImplementedBy<RepositoryFactories>()
                .LifestyleSingleton());

            container.Register(Component
                .For<IRepositoryProvider>()
                .ImplementedBy<RepositoryProvider>()
                .LifestylePerWebRequest());

            container.Register(Component
                .For<IProjUow>()
                .ImplementedBy<ProjUow>()
                .LifestylePerWebRequest());
        }

        private static BasedOnDescriptor FindControllers()
        {

            return AllTypes.FromThisAssembly()
                .BasedOn<IController>()
                .If(t => t.Name.EndsWith("Controller"));
        }
    }

WebWindsorInstaller

 internal class WebWindsorInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component
                .For<RepositoryFactories>()
                .ImplementedBy<RepositoryFactories>()
                .LifestyleSingleton());

            container.Register(Component
                .For<IRepositoryProvider>()
                .ImplementedBy<RepositoryProvider>()
                .LifestylePerWebRequest());

            container.Register(Component
                .For<IProjUow>()
                .ImplementedBy<ProjUow>()
                .LifestylePerWebRequest());

            container.Register(Classes
                .FromAssemblyContaining<Api.CategoriesController>()
                .BasedOn<IHttpController>()
                .If(t => t.Name.EndsWith("Controller"))
                .LifestylePerWebRequest());
        }
    }

我唯一不太明白的事情(尽管这很有效)是为什么我需要有两个几乎相同的类 DependencyResolver(WebApiWindsorDependencyResolver 和 MvcWindsorDependencyResolver)。我可以摆脱其中一个吗?

如果我更改代码而不是

DependencyResolver.SetResolver(new MvcWindsorDependencyResolver(Container)); 

我写

DependencyResolver.SetResolver(new WebApiWindsorDependencyResolver(Container)); 

它说

The type Proj.UI.Cms.Infrastructure.WebApiWindsorDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator.
Parameter name: commonServiceLocator

但两个类似乎共享相同的代码。

最好的问候。吉列尔莫。

【讨论】:

  • 也许一个类实现了两个接口?
  • 两者都实现相同的接口(IWindsorInstaller)
  • 对不起,我一直没有得到你的意思。你能告诉我哪个类应该实现现在没有实现的 IDependencyResolver 吗?谢谢!!吉列尔莫。
【解决方案2】:

如果有人仍然遇到此问题,解决方案是从 System.Web.Http.Dependencies 或 System.Web.Mvc 实现正确的 IDependencyResolver 接口。

请参阅https://stackoverflow.com/a/21459761 以获得答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    • 2014-11-07
    • 1970-01-01
    相关资源
    最近更新 更多