Simple Injector-确保控制器在生产中具有无参数的公共构造函数

本文关键字:参数 构造函数 确保 Injector- 控制器 生产中 Simple | 更新日期: 2023-09-27 18:09:38

我遇到了一个奇怪的情况。我遵循Onion Architecture,我的体系结构是这样的:

1-Core
     - Domain Classes
     - Repository Interfaces
     - Service Interfaces
2-Infrastructure
     - Data
     - Dependency Injection // Here I am using Simple Injector as dependency injection
     - Repository Interfaces Implementation
     - Service Interfaces Implementation
3-WebApi
     - Web Api Project
4-WebClient
     - My AngularJs App
5-Test
     - Test Project

依赖注入:

[assembly: PreApplicationStartMethod(typeof(IocConfig), "RegisterDependencies")]
namespace Infrastructure.DependencyResolution
{
    public class IocConfig
    {
        public static void RegisterDependencies()
        {
            var container = new Container();
            container.RegisterWebApiRequest<IRepositoryAsync<Category>, Repository<Category>>();
            container.RegisterWebApiRequest<ICategoryService, CategoryService>();
            container.RegisterWebApiRequest<IDataContextAsync>(() => new MyContext());
            container.Verify();
            GlobalConfiguration.Configuration.DependencyResolver =
            new SimpleInjectorWebApiDependencyResolver(container);
        }
    }
}

Web-Api项目:

public class HomeController : ApiController
{
    private readonly ICategoryService _categoryService;
    public HomeController(ICategoryService categoryService)
    {
        _categoryService = categoryService;
    }
}

我的local IIS上一切都很好。但现在我已经将这个应用程序发布到生产服务器上,现在它给了我以下错误:

{"message":"发生错误。","exceptionMessage":"错误尝试创建"HomeController"类型的控制器时发生。确保控制器具有无参数公共构造函数。","exceptionType":"System.InvalidOperationException","stackTrace":"在System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage请求,HttpControllerDescriptor controllerDescriptor,类型controllerType(''r''n位于System.Web.Http.Controller.HttpControllerDescriptor.CreateController(HttpRequestMessage请求(''r''nSystem.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext((","innerException":{"message":"出现错误。","exceptionMessage":"类型"JetAdz.WebApi.Controllers.HomeController"没有默认值构造函数","exceptionType":"System.ArgumentException","stackTrace":"位于System.Linq.Expressions.Expression.New(类型类型(''r''n位于System.Web.Http.Interal.TypeActivator.Create[TBase](类型instanceType(''r''nSystem.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage请求,类型controllerType,函数`1&activator(''r''nSystem.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage请求,HttpControllerDescriptor controllerDescriptor,类型控制器类型("}}

Simple Injector-确保控制器在生产中具有无参数的公共构造函数

请查看抛出异常的内部异常。它包含了描述为什么会发生这种情况的详细信息。

这里有多个问题。您应该确保在容器中显式注册所有根类型。控制器是根类型,因为它们是直接解析的(没有什么依赖于它们,但它们有依赖关系(。如果未显式注册它们,则在调用Verify()时,容器将无法检查是否可以创建它们。您可以通过调用以下命令来注册控制器:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

文档中对此进行了描述。

完成此操作后,您可能会在启动应用程序时直接看到Verify()方法失败,在这种情况下,您会得到一条非常详细的消息,解释出现了什么问题。

从内部异常中可以看到Web API的DefaultHttpControllerActivator.GetInstanceOrActivator方法正在调用TypeActivator.Create<T>(Type)。只有当对request.GetDependencyScope().GetService(controllerType)的调用返回null时才会发生这种情况。但是,如果您将SimpleInjectorWebApiDependencyResolver挂接到Web API管道中,这通常是不可能发生的。这是因为SimpleInjectorWebApiDependencyResolver在被请求解析IHttpController实现时永远不会返回null。相反,当无法解析控制器时,它将抛出异常。

因此,对我来说,这表明您的应用程序中存在绑定重定向问题。这意味着SimpleInjector.Integration.WebApi.dll引用的IHttpController版本与您的应用程序所使用的版本不同。绑定重定向就是为了解决这个问题,所以请确保您的应用程序具有正确的绑定。对于System.Web.Http.dll,它看起来是这样的(但请注意,您可能还需要其他绑定(:

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    ... 
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" 
          culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

通常,绑定由NuGet包管理器管理,但它无法定期进行管理。

当绑定重定向问题得到修复后,您将看到内部异常包含来自Simple Injector的信息,这些信息与您在调用Verify()时看到的信息相同。

您没有为WebApi注册正确的DependencyResolver。根据WebApi依赖注入页面和Simple Injector WebApi页面,应该这样做。

public static void Register(HttpConfiguration config)
{
    var container = new Container();
    container.RegisterWebApiRequest<IRepositoryAsync<Category>, Repository<Category>>();
    container.RegisterWebApiRequest<ICategoryService, CategoryService>();
    container.RegisterWebApiRequest<IDataContextAsync>(() => new MyContext());
    container.Verify();
    config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
    // Other Web API configuration not shown.
}

您所展示的配置是用于MVC依赖项注入的(您可能也需要(。

我使用spring XML文件将变量注入到我的类中。在我的情况下,当我创建一个新控制器时,它是一个复制/粘贴错误。

因此,虽然这与OP问题并不完全相关,但它会收到相同的错误消息,我会帮助其他人。

我已经复制了(尖括号改为方括号(:

[object id="className" type="Project.ClassName" scope="request"]
    [constructor-arg name="OtherClassName" ref="otherclassName"/]
[/object]

当我需要的是:

[object id="className" type="Project.ClassName" scope="request"]
    [property name="OtherClassName" ref="otherclassName"/]
[/object]

请注意属性,而不是构造函数arg

因为我的类没有一个寻找参数的构造函数。

对我来说,只是我忘记了将SimpleInjectorInitializer.Initialize();添加到我的Application_Start()中。

这些天,我通常在App_Start文件夹中创建一个SimpleInjectorInitializer类,在其中进行container.Verify()GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);调用;在我调用了GetInitializeContainer()方法之后,该方法正在执行所有类型注册等操作。