无法使用web api实例化使用Castle的Controller

时间:2012-11-22 21:07:46

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

我正在使用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工作正常,但另一个说:

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

为什么?

提前致谢!吉列尔莫。

2 个答案:

答案 0 :(得分:0)

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

这应该在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[] { };
        }
    }

ControllerInstaller

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

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

最诚挚的问候。吉列尔莫。

答案 1 :(得分:0)

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

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