質問

I'm working in a project that uses both ApiControllers and Controllers (not webapi) with Castle (from 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());
        }
    }

This in global.asax (Application_Start)

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

And this is the Controller constructor of CategoriesController

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

And ControllerBase inherites from Controller

The ApiController is defined as follows:

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

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

The ApiController works ok, but the other one says:

No parameterless constructor defined for this object.

Why?

Thanks in advance! Guillermo.

役に立ちましたか?

解決

Ok, Phil's link pointed me in the right direction. I'll share my solution in case anyone is having the same problem.

This should be in Global.asax.cx (Application_Start method)

// 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());
        }
    }

The only thing I don't get quite well (despite this works) is Why do I need to have two classes DependencyResolver (WebApiWindsorDependencyResolver and MvcWindsorDependencyResolver) when they are almost the same. Can I get rid of one of them?

If I change the code and instead of

DependencyResolver.SetResolver(new MvcWindsorDependencyResolver(Container)); 

I write

DependencyResolver.SetResolver(new WebApiWindsorDependencyResolver(Container)); 

It says

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

But both classes seems to share the same code.

Best Regards. Guillermo.

他のヒント

If someone is still experiencing this problem, the solution is to implement right IDependencyResolver interface either from System.Web.Http.Dependencies or from System.Web.Mvc.

See https://stackoverflow.com/a/21459761 for answer.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top