我正在尝试使用Ninject将EventLogger实例注入自定义ExceptionFilterAttribute。每当我运行代码时,EventLogger实例都为null。我已经实现了一个IFilterProvider,以类似的方式为我的自定义AuthorizationFilterAttribute解析依赖关系,并且工作正常。有什么想法吗?
不工作
public class ErrorHandlingAttribute : ExceptionFilterAttribute
{
[Inject]
public IEventLogger EventLogger { get; set; }
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
EventLogger.LogException(actionExecutedContext.Exception);
actionExecutedContext.Response = actionExecutedContext.Request.
CreateResponse(HttpStatusCode.BadRequest,
new ServiceErrorResponseDTO("An unhandled exception occurred while calling " +
actionExecutedContext.Request.RequestUri.ToString() +
". This event has been logged. If you continue to receive this error contact Weichert"));
}
}
工作
public class RequireAuthorizationAttribute : AuthorizationFilterAttribute
{
[Inject]
public IServiceRepository ServiceRepository { get; set; }
public override void OnAuthorization(HttpActionContext actionContext)
{
#region Header Authentication
var authHeader = actionContext.Request.Headers.Authorization;
if (authHeader != null)
{
自定义IFilterProvider
public class NinjectWebApiFilterProvider : IFilterProvider
{
private IKernel _kernel;
public NinjectWebApiFilterProvider(IKernel kernel)
{
_kernel = kernel;
}
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
var controllerFilters = actionDescriptor.ControllerDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Controller));
var actionFilters = actionDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Action));
var filters = controllerFilters.Concat(actionFilters);
foreach(var filter in filters)
{
_kernel.Inject(filter.Instance);
}
return filters;
}
}
NinjectWebCommon CreateKernel Method
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// Ad Ninject support for Web API.
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
GlobalConfiguration.Configuration.Services.Add(typeof(IFilterProvider),
new NinjectWebApiFilterProvider(kernel));
RegisterServices(kernel);
return kernel;
}
NinjectWebCommon绑定
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ServiceDbContext>().To<ServiceDbContext>();
kernel.Bind<IServiceRepository>().To<ServiceRepository>();
kernel.Bind<CareerDevelopmentDbContext>().To<CareerDevelopmentDbContext>();
kernel.Bind<ICareerDevelopmentRepository>().To<CareerDevelopmentRepository>();
kernel.Bind<ICareerDevelopmentService>().To<CareerDevelopmentService>();
kernel.Bind<IEventLogger>().To<ServiceEventLogger>();
kernel.Bind<IFilterProvider>().To<NinjectWebApiFilterProvider>().WithConstructorArgument("kernel", kernel);
}
答案 0 :(得分:4)
我遇到了同样的问题,并且通过将其添加到WebApiConfig.cs
中的过滤器集合中以相同的方式配置我的错误处理程序,这意味着它没有被我添加的FilterProvider
实现处理。所以我这样做了:
public class LoggingExceptionFilterAttribute : ExceptionFilterAttribute, IExceptionFilter
{
// this is what I wanted injected
private IEmailService emailService;
public LoggingExceptionFilterAttribute(IEmailService service)
{
emailService = service;
}
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
// my implementation here
}
}
然后我在NinjectWebCommon中注册了这样:
kernel.Bind<System.Web.Http.Filters.IExceptionFilter>().To<LoggingExceptionFilterAttribute>().InSingletonScope();
然后在WebApiConfig
我意识到我可以抓住DependencyResolver
所以我这样做了:
config.Filters.Add((IFilter)config.DependencyResolver.GetService(typeof(IExceptionFilter)));
现在Ninject处理构建我的异常过滤器,我甚至可以进行构造函数注入而不需要[Inject]
属性,而且我不必将ExceptionFilterAttribute
添加到每个API控制器。
答案 1 :(得分:1)
好的,您还必须确保绑定自定义IFilterProvider
。编写 Ninject.Web.WebApi 时,Nuget包是不稳定的,如果您使用它,它会自动为您执行。以同样的方式 Ninject.MVC3 为您的常规控制器执行此操作。
只要确保你有这个绑定,被替换的DependencyResolver
也将通过你的Ninject内核寻找IFilterProvider
实现:
kernel.Bind<IFilterProvider>().To<NinjectWebApiFilterProvider>();
然后,您的NinjectWebApiFilterProvider
将按照您的代码启动并将依赖项注入您的过滤器。