5

这篇文章是使用 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();
    }
}

导致以下错误:

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

有没有办法在使用 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);
    }

带我回到了起点。

终于解决了。

这是其他人的解决方案


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

以及 mvc 和 web api 控制器的注册

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


container.Register(Classes
    .FromAssemblyContaining<ValuesController>()
    .BasedOn<IHttpController>()
    .LifestyleScoped());
4

3 回答 3

6

微软似乎提倡将 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)。

于 2012-09-29T09:39:57.670 回答
0

如果您正在实现 IDependencyResolver 接口并将其与 Application_Start 中的框架连接起来,WindsorDependencyScope 将起作用:DependencyResolver.SetResolver()

于 2012-09-29T04:55:59.590 回答
0

为了让它在Owin Startup上工作,我覆盖DependencyResolverHttpConfiguration

[assembly: OwinStartup(typeof(YourCompany.API.Startup))]
namespace YourCompany.API
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
            var dependencyResolver = new WindsorHttpDependencyResolver(container);
            config.DependencyResolver = dependencyResolver;
            // ....... 
            // ....... 
        }
    }
}
于 2015-11-05T15:27:40.487 回答