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,类型控制器类型("}}
请查看抛出异常的内部异常。它包含了描述为什么会发生这种情况的详细信息。
这里有多个问题。您应该确保在容器中显式注册所有根类型。控制器是根类型,因为它们是直接解析的(没有什么依赖于它们,但它们有依赖关系(。如果未显式注册它们,则在调用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()
方法之后,该方法正在执行所有类型注册等操作。