用于依赖注入的 MVC Web API 和 Unity

Posted

技术标签:

【中文标题】用于依赖注入的 MVC Web API 和 Unity【英文标题】:MVC Web API and Unity for dependency injection 【发布时间】:2015-11-09 17:03:12 【问题描述】:

我正在构建一组非常简单的控制器,我想将依赖项注入其中。

我的 Web Api 项目使用 .net 4.5.1 (vs2015),我使用 Unity 进行依赖注入(对 Unity 来说真的很新)。

这是我所做的:

    新建项目 > ASP.Net Web 应用程序 > Web Api 项目(无身份验证) 工具 > Nuget 包管理器 > 管理解决方案的包... 搜索“Unity.MVC”并安装包。

    我创建了以下接口和类:

    public interface IExample
    
        void DoWork();
    
    
    public class ServiceA : IExample
    
        public void DoWork()
        
            Console.Write("A");
        
    
    
    public class ServiceB : IExample
    
        public void DoWork()
        
            Console.Write("B");
        
    
    

在我的简单控制器中,我实现了这个:

    public class HomeController : Controller
    
        IExample instance;

        public HomeController(IExample injected)
        
            instance = injected;
        

        public ActionResult Index()
        
            ViewBag.Title = "Home Page";

            return View();
        
    

我有这两个 Unity 新添加的文件:

我将以下代码添加到 UnityConfig.cs:

    public static void RegisterTypes(IUnityContainer container)
    
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your types here
        //container.RegisterType<IProductRepository, ProductRepository>();

        container.RegisterType<IExample, ServiceA>();
    

到目前为止 - 一切顺利!我按预期将 DI 放入视图中。现在我想为我的 web api 控制器做同样的事情,就像这样:

运行 - 并得到这个错误:

尝试创建“ItemController”类型的控制器时出错。确保控制器有一个无参数的公共构造函数。

我做错了什么?完全例外:


   "Message": "An error has occurred.",
   "ExceptionMessage": "An error occurred when trying to create a controller of type 'ItemController'. Make sure that the controller has a parameterless public constructor.",
   "ExceptionType": "System.InvalidOperationException",
   "StackTrace": "   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n   at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
   "InnerException":    
      "Message": "An error has occurred.",
      "ExceptionMessage": "Type 'WebApplication2.Controllers.ItemController' does not have a default constructor",
      "ExceptionType": "System.ArgumentException",
      "StackTrace": "   at System.Linq.Expressions.Expression.New(Type type)\r\n   at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"
   

提前致谢!

【问题讨论】:

由于某种原因,您的编辑被匿名用户标记为已提交,除非得到另一位用户的批准,否则不会显示。 根据您的(仍然建议的)更新,您只安装了 Unity.Mvc,它负责与 MVC 的 DependecyResolver 集成。对于 WebApi,您必须安装 Unity.WebAPI 包:nuget.org/packages/Unity.WebAPI 显示您的 WebApiConfig.csUnityMvcActivator.cs 以及最新软件包安装添加的任何新文件。 这确实有效 - 当我下载新包时,我必须重新注册类型代码!伟大的!!!!谢谢! :-))))) 【参考方案1】:

ControllerActivator 无法实例化您的HomeController,因为它的构造函数没有标记为public(因此它实际上是private)。

当您根本不提供任何构造函数时,编译器会自动为您创建一个public,但由于您正在提供一个(不是public),因此您将结束没有公共构造函数。

试试这个:

public HomeController(IExample injected)

    instance = injected;

更新:

根据您的编辑,要将 Unity 与 API 控制器集成,您还必须安装 Unity.WebAPI 包。

有关 WebAPI 集成的更多信息:http://www.asp.net/web-api/overview/advanced/dependency-injection

【讨论】:

我引用了错误的 Unity 包 - 现在将 Unity.WebAPI 包用于 MVC Web API 项目。谢谢!!【参考方案2】:

要在 Web API 中使用统一的依赖注入,请使用以下步骤。

    在您的 Web API 项目中安装 Unity 包。 转到包管理器控制台粘贴下面的命令以安装 Unity

      Install-Package Unity.WebAPI -Version 5.3.0
    

    安装Unity后,在Web API的APP_Start文件夹中,添加一个名为UnitConfig.cs的文件,在该文件中注册你的服务接口和服务逻辑类。

     public static class UnityConfig
      
        public static void RegisterComponents()
         
           var container = BuildUnityContainer();
           GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
         
       private static IUnityContainer BuildUnityContainer()
        
          var container = new UnityContainer();                    
          container.RegisterType<ICategoryService, CategoryService> ().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());
          return container;
           
      
    

    在Web API Global.asax文件的Application_Start()方法中注册上述RegisterComponents()方法

       protected void Application_Start()
       
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        UnityConfig.RegisterComponents();
       
    

    最后一步是将服务接口注入到 Web AIP 控制器构造函数中。

      public CategoryController(ICategoryService Iinject)
      
        this._categoryServices= Iinject;
      
    

【讨论】:

.RegisterType 在这个块 UnitOfWork 没有得到。参考问题对此有任何想法

以上是关于用于依赖注入的 MVC Web API 和 Unity的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

web api中的依赖注入

ASP.NET Core Web 应用程序系列- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)

web API .net - .net core 对比学习-依赖注入