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

时间:2011-10-05 15:15:35

标签: asp.net-mvc-3 dependency-injection ninject

我正在为我的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);
        }       
    }
}

在global.asax中我注册了处理程序和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)如果已实现Singleton模式,请改为使用与InSingletonScope()的绑定。

Source Error: 


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

花了一天时间,学到很多关于依赖注射的知识,这很好,但我在这里做错了什么?

1 个答案:

答案 0 :(得分:3)

Ninject.Web.Mvc具有内置的名为“BindFilter”的功能,它允许您将属性(需要一些或不带构造函数的args)映射到过滤器(其中注入了构造函数args)。此外,您可以使用它来复制属性中的值,并根据需要将它们作为构造函数args注入过滤器。它还允许您将过滤器的范围更改为每个操作或每个控制器等,以便实际重新实例化(正常操作过滤器不会根据请求重新实例化)。

以下是example我如何使用它来执行UoW动作过滤器。