Castle Windsor ASP.NET MVC 4和Web API相同的应用程序.只有MVC控制器没有依赖关系?

lsf*_*era 5 c# asp.net castle-windsor asp.net-mvc-4 asp.net-web-api

本文是使用Castle Windsor进行Web API的一个很好的起点,但是如果我创建一个简单的MVC控制器呢?只有在注入没有依赖性时它才有效.

添加这个,即:

public class HomeController : Controller
{
    private readonly IValuesRepository repository;

    public HomeController(IValuesRepository repository)
    {
        this.repository = repository;
    }

    public ActionResult Index()
    {
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

为此对象定义的无参数构造函数

有没有办法在使用Castle Windsor的同一个应用程序中使用MVC和Web API逻辑?

设置完成后DependencyResolver.SetResolver(...)application_start,我没有注意到我的应用程序有任何改善.

如你看到的.

WebApiScopedLifetimeDependencyResolverSample.Windsor.WindsorDependencyResolver类型似乎没有实现

实现服务定位器:

internal sealed class WindsorDependencyResolver
    : ServiceLocatorImplBase, IDependencyResolver
{
    private readonly IWindsorContainer container;

    public WindsorDependencyResolver(
        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 WindsorDependencyScope(this.container);
    }

    public void Dispose()
    {
    }

    protected override object DoGetInstance(
        Type serviceType, string key)
    {
        if (key != null)
            return container.Resolve(key, serviceType);
        return container.Resolve(serviceType);
    }

    protected override IEnumerable<object> DoGetAllInstances(
        Type serviceType)
    {
        return (object[])container.ResolveAll(serviceType);
    }
Run Code Online (Sandbox Code Playgroud)

把我带回了起点.

终于解决了.

这是其他人的解决方案


在application_start中......

//mvc
DependencyResolver.SetResolver(
    new WindsorMvcDependencyResolver(container));

// web api:
var httpDependencyResolver = 
    new WindsorHttpDependencyResolver(container);

GlobalConfiguration.Configuration.DependencyResolver =
    httpDependencyResolver;

internal class WindsorMvcDependencyResolver
    : WindsorDependencyScope, IDependencyResolver
{
    private readonly IWindsorContainer container;

    public WindsorMvcDependencyResolver(
        IWindsorContainer container) : base(container)
    {
        this.container = container;
    }
}


internal sealed class WindsorHttpDependencyResolver
    : IDependencyResolver
{
    private readonly IWindsorContainer container;

    public WindsorHttpDependencyResolver(
        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 WindsorDependencyScope(this.container);
    }

    public void Dispose()
    {
    }
}

internal class WindsorDependencyScope : IDependencyScope
{
    private readonly IWindsorContainer container;
    private readonly IDisposable scope;

    public WindsorDependencyScope(
        IWindsorContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        this.container = container;
        this.scope = container.BeginScope();
    }

    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 void Dispose()
    {
        this.scope.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

并注册了mvc和web api控制器

container.Register(Classes
    .FromAssemblyContaining<HomeController>()
    .BasedOn<Controller>()
    .LifestylePerWebRequest());


container.Register(Classes
    .FromAssemblyContaining<ValuesController>()
    .BasedOn<IHttpController>()
    .LifestyleScoped());
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 6

Microsoft似乎推动将Web API放入与MVC应用程序相同的项目中(由他们使用的模板引起).但是,我不会将Web API和MVC应用程序混合到同一个项目/网站中.需求和(DI)配置很可能需要不同,这将使得使用单个容器配置解决此问题的一切变得复杂.

因此,虽然完全有可能在同一个应用程序中运行MVC和Web API,并且可以使用单个容器,但我的建议是:不要这样做.不仅从技术角度,而且从功能.Web API是一种Web服务.您也不会在同一个项目中将MVC与WCF混合使用.

但是如果你真的想要,你只需要注册System.Web.Mvc.DependencyResolver.SetResolver(对于MVC)和System.Web.Http.HttpConfiguration.DependencyResolver(对于Web API).