如何在ASP.NET MVC的RegisterGlobalFilters方法中进行依赖项注入 [英] How to do dependency injection inside ASP.NET MVC's RegisterGlobalFilters method

查看:244
本文介绍了如何在ASP.NET MVC的RegisterGlobalFilters方法中进行依赖项注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对使用IOC容器还是有点陌生​​,但我还在努力.我正在将ASP.NET MVC 5.2与Ninject.MVC3一起使用.我有一个异常过滤器,基本上可以移交给日志服务:

I am still a bit new to using IOC containers and I'm struggling a bit. I am using ASP.NET MVC 5.2 with Ninject.MVC3. I have an exception filter that basically hands off to a log service:

public class ExceptionLoggerFilter : IExceptionFilter
{
    private readonly ILogService _logService;

    public ExceptionLoggerFilter(ILogService logService) {
        _logService = logService;
    }

    public void OnException(ExceptionContext filterContext) {
        _logService.LogError(filterContext.Exception);
    }
}

我想使用依赖注入来获取日志服务的实例.但是,RegisterGlobalFilters方法是静态的:

I would like to use dependency injection to get the instance of the log service. However, the RegisterGlobalFilters method is static:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ExceptionLoggerFilter(???));
    }
}

我可以为FilterConfig使用静态构造函数,但这并不是一个好的解决方案.

I could use a static constructor for FilterConfig, but this just doesn't feel like a good solution.

我尝试在ExceptionLoggerFilter类中使用属​​性注入,但是它没有用(LogService始终为null):

I tried using property injection in the ExceptionLoggerFilter class, but it just didn't work (LogService was always null):

[Inject]
public ILogService LogService { get; set; }

我已经阅读了使用Factory模式的内容,但是在这里似乎无济于事,因为我仍然需要将Factory类注入到FilterConfig类的静态构造函数中.我可能是错的,但这也不是正确的解决方案.

I have read up on using the Factory pattern, but it doesn't seem to help here as I would still need to inject the Factory class into the static constructor of the FilterConfig class. I could be wrong, but this doesn't feel like the right solution either.

目前,我使用的是给我一个实例"方法:

For now, I'm using a just-give-me-an-instance method:

var logService = (ILogService)DependencyResolver.Current.GetService(typeof(ILogService));
filters.Add(new ExceptionLoggerFilter(logService));

这可行,但这是一个好的解决方案吗?有没有更好的办法?我是否在考虑依赖注入和IOC容器?

This works, but is it a good solution? Is there a better way? Is my thinking about dependency injection and IOC containers all messed up?

推荐答案

MVC全局过滤器只是实例列表.这意味着此类过滤器所具有的任何依存关系也将变成单例.这意味着您应该非常谨慎地使用此方法,因为偶然导致

MVC global filters are just a list of instances. This means that any dependencies such filter has, also become singletons. This means you should be very careful with this approach, because it is really easy to accidentally cause a Captive Dependency in your application. Captive Dependencies are often hard to track and often only popup in testing or production.

相反,您应该创建一个代理类,该代理类可以在使用过滤器时委派回您的容器/内核,以便可以当场解析实际的过滤器.这样可以防止强制依赖性.

Instead, you should create a proxy class that can delegate back to your container/kernel at the time the filter is used, so it can resolve the real filter on the spot. This prevents Captive Dependencies.

这种代理可以如下所示:

Such proxy can look as follows:

public class NinjectExceptionFilterProxy<TExceptionFilter> : IExceptionFilter
    where TExceptionFilter : IExceptionFilter
{
    private readonly Kernel _kernel;

    public ExceptionLoggerFilter(Kernel kernel) {
        _kernel = kernel;
    }

    public void OnException(ExceptionContext filterContext) {
        var filter = _kernel.Get<TExceptionFilter>();
        filter.OnException(filterContext);
    }
}

您可以按以下方式注册代理过滤器:

You can register the proxy filter as follows:

public static void RegisterGlobalFilters(GlobalFilterCollection filters, IKernel kernel)
{
    filters.Add(new NinjectExceptionFilterProxy<ExceptionLoggerFilter>(kernel));
}

这篇关于如何在ASP.NET MVC的RegisterGlobalFilters方法中进行依赖项注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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