如何使用Ninject注入服务到MVC 3 FilterAttributes? [英] How to use Ninject to inject services into MVC 3 FilterAttributes?

查看:118
本文介绍了如何使用Ninject注入服务到MVC 3 FilterAttributes?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我正在使用Ninject 2.2,它可以适用于其他功能,例如通过控制器构造函数进行注册存储库和聚合服务。



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



界面如下:

 命名空间Foo.WebUI.Infrastructure 
{
public interface ILogger
{
void Log(Exception e);
}
}

事件查看器记录器实现

 命名空间Foo.WebUI.Infrastructure 
{
///< summary>
///将异常记录到Windows事件查看器
///< / summary>
public class EventViewerLogger:ILogger
{
private EventViewerLogger _logger = null;

EventViewerLogger()
{
_logger = new EventViewerLogger();
}

public void Log(Exception e)
{
_logger.Log(e);
}
}
}

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

 命名空间Foo.WebUI.Handlers 
{
///< summary>
///具有记录日志异常的接口的自定义错误处理程序
///< / summary>
public class CustomHandleErrorAttribute:HandleErrorAttribute
{
[Inject]
public ILogger Logger {get;组; }

//默认构造函数
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 NinjectInfrastructureModule());
}

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

 命名空间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);



//迭代所有过滤器并使用Ninject内核来提供具体的实现
foreach(过滤器中的过滤器)
{
kernel.Inject(filter.Instance);
}

返回过滤器;
}
}
}

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



激活路径:
2)将依赖关系ILogger注入属性CustomHandleErrorAttribute类型的记录器
1)请求CustomHandleErrorAttribute



建议:
1)确保实现类型具有公共构造函数。
2)如果您已实现Singleton模式,请改用InSingletonScope()绑定。

 源错误: 


第27行:foreach(过滤器中的过滤器)
行28:{
行29:kernel.Inject(filter.Instance);
行30:}

花了一天时间,了解了很多关于依赖注入很好,但是我在这里做错了什么?

解决方案

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



这是一个示例,我如何使用它来执行UoW操作过滤器。


I'm writing a custom ErrorHandler attribute for my MVC project. I would like to inject an implementation of EventViewerLogger into that attribute.

I'm using Ninject 2.2 and it works fine for other features, such as injection repositories and aggregate services through controller constructors.

I understand that I can't inject an implementation of some class into attribute through constructor, therefore I have to inject it into the attribute's property.

Interface is below:

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

Event viewer logger implementation

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);
        }
    }
}

Below is code for error handler:

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);
        }       
    }
}

In global.asax I register the handler and Ninject.

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

Finally, I have a custom filter provider

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;
        }        
    }
}

When I start the application I get the following exception:

Activation path: 2) Injection of dependency ILogger into property Logger of type CustomHandleErrorAttribute 1) Request for CustomHandleErrorAttribute

Suggestions: 1) Ensure that the implementation type has a public constructor. 2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead.

Source Error: 


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

Spent a day on this, learnt a lot about dependecy injection which is great, but what am I doing wrong here?

解决方案

Ninject.Web.Mvc has this functionality built in called "BindFilter" which lets you map an attribute (that takes some or no constructor args) to a filter (which has its constructor args injected). Additionally, you can use it to copy values from the attribute and inject them as constructor args to the filter if you want. It also lets you change scope on your filters to be per action or per controller etc so that they actually get re-instantiated (normal action filters don't get re-instantiated per request).

Here's an example of how I've used it to do a UoW action filter.

这篇关于如何使用Ninject注入服务到MVC 3 FilterAttributes?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆