简单的注射器无法注入Web API控制器中的依赖项
我试图做一些基本的构造函数DI与简单的注入器,似乎无法解决Web API控制器的依赖关系。
- 我有一个“API”文件夹,这是“控制器”文件夹之外的API控制器。
- 我也尝试把它放在“控制器”文件夹,但似乎没有多大的区别。 我收到的堆栈跟踪与此问题中提供的相似。
- 我正在使用“Simple Injector MVC集成快速入门”NuGet软件包(第2.1.0版)的全新安装。
- 我从文档中获得了基本的SimpleInjectorWebApiDependencyResolver,这与在这里find的一样。
- 我正在使用entity framework,并已查看有关正确加载上下文的更改的讨论线程 。
这似乎不是一个问题,但我仍然收到以下错误:
types“MyProject.API.ArticleController”没有默认的构造函数
System.ArgumentException在
System.Web.Http.Internal.TypeActivator.Create [TBase](typesinstanceType)在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage请求,Type控制器types)System.Linq.Expressions.Expression.New ,Func`1&activator)在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage请求,HttpControllerDescriptor controllerDescriptor,typescontrollerType)
如果有人能提供一些build议,请问是否应该修改其当前状态/呼叫顺序。
ArticleController(基本结构):
 public class ArticleController : ApiController { private readonly IArticleRepository articleRepository; private readonly IUserRepository userRepository; private readonly IReleaseRepository releaseRepository; public ArticleController(IArticleRepository articleRepository, IUserRepository userRepository, IReleaseRepository releaseRepository) { this.articleRepository = articleRepository; this.userRepository = userRepository; this.releaseRepository = releaseRepository; } // GET api/Article public IEnumerable<Article> GetArticles(){ // code } // GET api/Article/5 public Article GetArticle(int id){ // code } // PUT api/Article/5 public HttpResponseMessage PutArticle(int id, Article article){ // code } // POST api/Article public HttpResponseMessage PostArticle(ArticleModel article){ // code } // DELETE api/Article/5 public HttpResponseMessage DeleteArticle(int id){ // code } } 
SimpleInjectorInitializer:
 public static class SimpleInjectorInitializer { public static void Initialize() { var container = new Container(); InitializeContainer(container); container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); container.RegisterMvcAttributeFilterProvider(); container.Verify(); DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); } private static void InitializeContainer(Container container) { container.Register<IArticleRepository, ArticleRepository>(); container.Register<IUserRepository, UserRepository>(); container.Register<IReleaseRepository, ReleaseRepository>(); } } 
的Global.asax.cs:
 public class WebApiApplication : System.Web.HttpApplication { private void ConfigureApi() { // Create the container as usual. var container = new Container(); // Verify the container configuration // container.Verify(); // Register the dependency resolver. GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); ConfigureApi(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); } } 
	
TLTR:问题是由Web API处理parsing控制器types的隐式方式引起的; 注册您的Web API控制器明确,你会看到问题的地方。
以下是一步一步发生的事情:
-   System.Web.Http.DefaultHttpControllerActivator调用SimpleInjectorWebApiDependencyResolver并请求创build一个API控制器。
-   SimpleInjectorWebApiDependencyResolver将该调用转发给SimpleInjector.Container实例。
-  但是, Container实例没有为该API控制器显式注册(因为您向parsing器提供了一个空容器)。
- 由于没有明确的注册,容器试图为该types进行最后一刻的注册。
- 然而,该控制器types取决于不能解决的接口,因为它们没有注册在容器(记住,你的容器是空的)。
-  尽pipe容器通常会抛出一个exception,但在这种情况下返回null,因为types是通过IServiceProvider.GetService方法请求的,并且types未被明确注册。
-   SimpleInjectorWebApiDependencyResolver的GetService方法也会返回null,因为按照定义它应该返回null; 当不存在注册时(当前是这种情况)它应该返回null。
-  由于DependencyResolver返回null,因此DefaultHttpControllerActivator将回退到其默认行为,这意味着创build该types本身,但这需要控制器具有默认构造函数。
长话短说,这个问题是由Web API处理parsing控制器types的隐式方式引起的。
所以这里的解决scheme是:
-  在您的Web应用程序中只有一个Container。 这可以防止configuration的各种麻烦和复杂性。
-  在容器中显式注册所有Web API控制器。 显式注册控制器将确保简单注入器将在控制器无法parsing时抛出exception。 此外,这允许您调用container.Verify(),这将使configuration无效( 可validation的configuration很重要 )启动期间应用程序失败。 这也使您能够诊断configuration ,使您对configuration的正确性更有信心。
我的build议是将MVC和Web API放在他们自己的项目中 。 这将使事情变得更容易。
注册所有的Web API控制器可以用下面的代码完成:
 container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 
更新:
 由于此错误非常常见,因此在请求控制器types时, SimpleInjectorWebApiDependencyResolver类的较新版本将不会返回null 。 相反,它会抛出一个描述性的错误。 因此,只要使用官方的SimpleInjectorWebApiDependencyResolver ,就不会再看到错误。