无法使用Unity将依赖项注入ASP.NET Web API控制器

Ove*_*d D 81 .net c# unity-container asp.net-web-api

有没有人使用IoC容器运行将依赖项注入ASP.NET WebAPI控制器?我似乎无法让它发挥作用.

这就是我现在正在做的事情.

在我的global.ascx.cs:

    public static void RegisterRoutes(RouteCollection routes)
    {
            // code intentionally omitted 
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        IUnityContainer container = BuildUnityContainer();

        System.Web.Http.GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
            t =>
            {
                try
                {
                    return container.Resolve(t);
                }
                catch (ResolutionFailedException)
                {
                    return null;
                }
            },
            t =>
            {
                try
                {
                    return container.ResolveAll(t);
                }
                catch (ResolutionFailedException)
                {
                    return new System.Collections.Generic.List<object>();
                }
            });

        System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container)); 

        BundleTable.Bundles.RegisterTemplateBundles();
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer().LoadConfiguration();

        return container;
    }
Run Code Online (Sandbox Code Playgroud)

我的控制器工厂:

public class UnityControllerFactory : DefaultControllerFactory
            {
                private IUnityContainer _container;

                public UnityControllerFactory(IUnityContainer container)
                {
                    _container = container;
                }

                public override IController CreateController(System.Web.Routing.RequestContext requestContext,
                                                    string controllerName)
                {
                    Type controllerType = base.GetControllerType(requestContext, controllerName);

                    return (IController)_container.Resolve(controllerType);
                }
            }
Run Code Online (Sandbox Code Playgroud)

它似乎永远不会在我的统一文件中查找解决依赖关系,我得到一个错误,如:

尝试创建"PersonalShopper.Services.WebApi.Controllers.ShoppingListController"类型的控制器时发生错误.确保控制器具有无参数的公共构造函数.

在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpControllerContext controllerContext,类型controllerType)在System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance(HttpControllerContext controllerContext,HttpControllerDescriptor controllerDescriptor)在System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController (HttpControllerContext controllerContext,字符串controllerName)在System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage请求,的CancellationToken的CancellationToken)在System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage请求,的CancellationToken的CancellationToken)

控制器看起来像:

public class ShoppingListController : System.Web.Http.ApiController
    {
        private Repositories.IProductListRepository _ProductListRepository;


        public ShoppingListController(Repositories.IUserRepository userRepository,
            Repositories.IProductListRepository productListRepository)
        {
            _ProductListRepository = productListRepository;
        }
}
Run Code Online (Sandbox Code Playgroud)

我的统一文件看起来像:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <container>
    <register type="PersonalShopper.Repositories.IProductListRepository, PersonalShopper.Repositories" mapTo="PersonalShopper.Implementations.MongoRepositories.ProductListRepository, PersonalShopper.Implementations" />
  </container>
</unity>
Run Code Online (Sandbox Code Playgroud)

请注意,我没有控制器本身的注册,因为在以前的mvc版本中,控制器工厂会发现需要解决依赖关系.

好像我的控制器工厂从未被调用过.

Ove*_*d D 42

弄清楚了.

对于ApiControllers,MVC 4使用System.Web.Http.Dispatcher.IHttpControllerFactorySystem.Web.Http.Dispatcher.IHttpControllerActivator来创建控制器.如果没有静态方法来注册它们的实现是什么; 当它们被解析时,mvc框架在依赖项解析器中查找实现,如果找不到它们,则使用默认实现.

通过执行以下操作,我获得了控制器依赖项的统一解析:

创建了一个UnityHttpControllerActivator:

public class UnityHttpControllerActivator : IHttpControllerActivator
{
    private IUnityContainer _container;

    public UnityHttpControllerActivator(IUnityContainer container)
    {
        _container = container;
    }

    public IHttpController Create(HttpControllerContext controllerContext, Type controllerType)
    {
        return (IHttpController)_container.Resolve(controllerType);
    }
}
Run Code Online (Sandbox Code Playgroud)

注册控制器激活器作为统一容器本身的实现:

protected void Application_Start()
{
    // code intentionally omitted

    IUnityContainer container = BuildUnityContainer();
    container.RegisterInstance<IHttpControllerActivator>(new UnityHttpControllerActivator(container));

    ServiceResolver.SetResolver(t =>
       {
         // rest of code is the same as in question above, and is omitted.
       });
}
Run Code Online (Sandbox Code Playgroud)

  • 这篇文章已经过时了.有关MVC RC的清洁解决方案,请参阅CodeKata的回复. (7认同)

小智 37

有一个更好的解决方案在这里正常工作

http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver

  • 不是链接到博客的忠实粉丝 - 你能在这里总结并把链接?:) (22认同)
  • 它看起来像一个很好的方法,但我得到了几个错误,如下面.看起来新的解析器无法解析多种类型.依赖项的解析失败,type ="System.Web.Http.Hosting.IHostBufferPolicySelector",name ="(none)".在解决时发生异常:异常是:InvalidOperationException - IHostBufferPolicySelector类型没有可访问的构造函数.---在异常时,容器是:Resolving System.Web.Http.Hosting.IHostBufferPolicySelector,( (3认同)

Pau*_*les 22

您可能需要查看Unity.WebApi NuGet包,它将对所有这些进行排序,并且还可以满足IDisposable组件的需要.

看到

http://nuget.org/packages/Unity.WebAPI

要么

http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package

  • 这里有一篇很好的博客文章(http://netmvc.blogspot.com/2012/04/dependency-injection-in-aspnet-mvc-4.html),其中有一个使用Unity.mvc3组合的演练(适用于MVC4,以及Unit.WebApi非常干净地实现DI. (2认同)

gar*_*thb 9

微软已经为此创建了一个包.

从包管理器控制台运行以下命令.

安装包Unity.AspNet.WebApi

如果您已经安装了Unity,它将询问您是否要覆盖App_Start\UnityConfig.cs.回答否并继续.

无需更改任何其他代码,DI(带统一)将起作用.