c# - NInject v3.3.4 和 WebApi 2,没有无参数构造函数
问题描述
请用 NInject 和 Web API 2 帮助我摆脱困境。我有一个 WebApi 项目。我安装了 Ninject.Web.WebApi.WebHost v3.3.0 Nuget。这带来了
- Ninject.Web.WebApi.WebHost v3.3.0
- Ninject.Web.WebApi v3.3.0
- Ninject.Web.Common.WebHost v3.3.1
- Ninject.Web.Common v3.3.1
- 忍者 v3.3.4
其中之一在 App_Start 文件夹中生成了一个 Ninject.Web.Common.cs。我为我的图表修改了其中的 RegisterServices 方法:
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Load<SubscriptionApiModule>();
}
正在加载的模块包含 IQuerySubscription 的绑定:
namespace SubscriptionApi.Models
{
...
public class SubscriptionApiModule : NinjectModule
{
public override void Load()
{
Bind<IQuerySubscription>().To<QueryMultipubForSubscription>();
...
}
}
}
我对 SubscriptionApiModule 的配置很有信心。我有单元测试提供证据证明带有 SubscriptionApiModule 的 StandardKernel 将响应 .Get 带有我期望的具体类的请求。
我有几个控制器。这是一个:
[RoutePrefix("api/SubscriptionCheck")]
public class SubscriptionCheckController : ApiController
{
public SubscriptionCheckController(IQuerySubscription queryService)
{
QueryService = queryService;
}
private IQuerySubscription QueryService { get; }
[HttpGet]
[Route("Heartbeat")]
public string Heartbeat()
{
return "thump";
}
[HttpGet]
[Route("Get/{email}/{productCode}")]
[EnableCors(origins: "*", headers: "*", methods:"*")]
public async Task<bool> Get(string email, string productCode)
{
return await QueryService.IsSubscribed(email, productCode);
}
}
我添加了一个用于诊断的心跳。我运行 API 并在浏览器地址中输入http://localhost:xxxxx/api/SubscriptionCheck/Heartbeat并显示响应:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
An error occurred when trying to create a controller of type 'SubscriptionCheckController'. Make sure that the controller has a parameterless public constructor.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
</StackTrace>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'SubscriptionApi.Controllers.SubscriptionCheckController' does not have a default constructor
</ExceptionMessage>
<ExceptionType>System.ArgumentException</ExceptionType>
<StackTrace>
at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
</StackTrace>
</InnerException>
</Error>
显然,该容器尚未向 Web Api 2 框架注册。有时,我应用了一个曾经有效的旧技巧。在 CreateKernel 方法中,在 RegisterServices(kernel) 之后:
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
这让我在启动时出现异常:
Ninject.ActivationException HResult=0x80131500 消息=使用从 ModelValidatorProvider 到 NinjectDefaultModelValidatorProvider 的绑定激活 ModelValidatorProvider 时出错 在两个服务的构造函数之间检测到循环依赖。
激活路径:3)将依赖ModelValidatorProvider注入到DefaultModelValidatorProviders类型的构造函数的参数defaultModelValidatorProviders 2)将依赖DefaultModelValidatorProviders注入到NinjectDefaultModelValidatorProvider类型的构造函数的参数defaultModelValidatorProviders 1)对ModelValidatorProvider的请求
建议: 1) 确保您没有声明 ModelValidatorProvider 对服务的任何实现的依赖。2) 考虑将服务组合成一个服务以消除循环。3) 使用属性注入代替构造函数注入,如果需要在注入属性值后运行初始化逻辑,则实现 IInitializable。
来源=堆栈跟踪:
为此,我尝试了我在 SO 某处读到的 hack。我在调用 RegisterServices 和分配给 .DependencyResolver 之前添加到 CreateKernel:
System.Collections.Generic.IEnumerable<object> configuredObjects =
GlobalConfiguration.Configuration.Services.GetServices(
typeof(System.Web.Http.Validation.ModelValidatorProvider));
System.Collections.Generic.IEnumerable<System.Web.Http.Validation.ModelValidatorProvider> configuredProviders =
configuredObjects.Cast<System.Web.Http.Validation.ModelValidatorProvider>();
Ninject.Web.WebApi.Filter.DefaultModelValidatorProviders defaultProviders =
new Ninject.Web.WebApi.Filter.DefaultModelValidatorProviders(configuredProviders);
kernel
.Bind<Ninject.Web.WebApi.Filter.DefaultModelValidatorProviders>()
.ToConstant(defaultProviders);
这给了我一个例外:
Ninject.ActivationException HResult=0x80131500 Message=错误激活 DefaultModelValidatorProviders 有多个匹配的绑定可用。匹配绑定:1)从 DefaultModelValidatorProviders 绑定到常量值 2)从 DefaultModelValidatorProviders 绑定到常量值激活路径:2)将依赖项 DefaultModelValidatorProviders 注入到 NinjectDefaultModelValidatorProvider 类型的构造函数的参数 defaultModelValidatorProviders 1)对 ModelValidatorProvider 的请求
建议: 1) 确保您只为 DefaultModelValidatorProviders 定义了一次绑定。
来源=堆栈跟踪:
你能提供一种方法让 NInject 注册到 WebApi 控制器吗?