如何使用Ninject将服务注入MVC 3 FilterAttributes



我正在为我的MVC项目编写自定义ErrorHandler属性。我想注入EventViewerLogger的实现到该属性中。

我正在使用Ninject 2.2,它在其他功能上工作得很好,比如注入存储库和通过控制器构造函数聚合服务。

我知道我不能通过构造函数将某些类的实现注入到属性中,因此我必须将其注入到属性的属性中。

接口如下:

namespace Foo.WebUI.Infrastructure
{
    public interface ILogger
    {        
        void Log(Exception e);
    }
}

事件查看器日志实现

namespace Foo.WebUI.Infrastructure
{
    /// <summary>
    /// Logs exceptions into the Windows Event Viewer
    /// </summary>
    public class EventViewerLogger: ILogger
    {
        private EventViewerLogger _logger = null;        
        EventViewerLogger() 
        {
            _logger = new EventViewerLogger();
        }
        public void Log(Exception e)
        {
            _logger.Log(e);
        }
    }
}

下面是错误处理程序的代码:

namespace Foo.WebUI.Handlers
{
    /// <summary>
    /// Custom error handler with an interface to log exceptions
    /// </summary>
    public class CustomHandleErrorAttribute: HandleErrorAttribute
    {   
        [Inject]
        public ILogger Logger { get; set; }        
        // Default constructor
        public CustomHandleErrorAttribute():base() { }        
        public override void OnException(ExceptionContext filterContext)
        {           
            Logger.Log(filterContext.Exception);                        
            base.OnException(filterContext);
        }       
    }
}

在全球。当我注册处理程序和Ninject。

protected void Application_Start()
{
   IKernel kernel = new StandardKernel(new NinjectInfrastructureModule());
}

最后,我有一个自定义过滤器提供程序

namespace Foo.WebUI.Infrastructure
{
    public class NinjectFilterProvider: FilterAttributeFilterProvider
    {
        private readonly IKernel kernel;
        public NinjectFilterProvider(IKernel kernel)
        {
            this.kernel = kernel;
        }
        public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {            
            var filters = base.GetFilters(controllerContext, actionDescriptor);

            // Iterate through all the filters and use Ninject kernel to serve concrete implementations
            foreach (var filter in filters)
            {       
                kernel.Inject(filter.Instance);
            }
            return filters;
        }        
    }
}

当我启动应用程序时,我得到以下异常:

激活路径:2)将依赖ILogger注入到CustomHandleErrorAttribute类型的属性Logger中1)请求CustomHandleErrorAttribute

建议:1)确保实现类型有一个公共构造函数。2)如果你已经实现了单例模式,那就使用绑定InSingletonScope()来代替。

Source Error: 

Line 27:             foreach (var filter in filters)
Line 28:             {       
Line 29:                 kernel.Inject(filter.Instance);
Line 30:             }

花了一天的时间,学到了很多关于依赖注入这是伟大的,但我在这里做错了什么?

。Mvc有一个内置的名为"BindFilter"的功能,它可以让你将一个属性(它接受一些或没有构造函数参数)映射到一个过滤器(它有它的构造函数参数注入)。此外,如果需要,还可以使用它来复制属性中的值,并将它们作为构造函数参数注入过滤器。它还可以让你改变过滤器的作用域为每个动作或每个控制器等,这样它们就会被重新实例化(普通的动作过滤器不会每个请求都被重新实例化)。

这里有一个例子,我是如何使用它来做一个UoW动作过滤器

最新更新