asp.net-mvc - 如何在 ASP.NET MVC 的 RegisterGlobalFilters 方法中进行依赖项注入(inject)

标签 asp.net-mvc dependency-injection ninject ioc-container

我对于使用 IOC 容器还是有点陌生​​,而且有点挣扎。我正在使用 ASP.NET MVC 5.2 和 Ninject.MVC3。我有一个异常过滤器,基本上将其交给日志服务:

public class ExceptionLoggerFilter : IExceptionFilter
{
    private readonly ILogService _logService;

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

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

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

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

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

我尝试在 ExceptionLoggerFilter 类中使用属​​性注入(inject),但它不起作用(LogService 始终为 null):

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

我已经阅读了有关使用 Factory 模式的内容,但它似乎没有帮助,因为我仍然需要将 Factory 类注入(inject) FilterConfig 类的静态构造函数中。我可能是错的,但这也不是正确的解决方案。

目前,我使用的是 just-give-me-an-instance 方法:

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

这可行,但这是一个好的解决方案吗?有没有更好的办法?我对依赖注入(inject)和 IOC 容器的想法是否都困惑了?

最佳答案

MVC 全局过滤器只是实例列表。这意味着此类过滤器具有的任何依赖项也将成为单例。这意味着您应该非常小心这种方法,因为很容易意外地导致 Captive Dependency在您的应用程序中。强制依赖项通常很难跟踪,并且通常只在测试或生产中弹出。

相反,您应该创建一个代理类,它可以在使用过滤器时委托(delegate)回您的容器/内核,以便它可以当场解析真正的过滤器。这可以防止强制依赖关系。

此类代理可以如下所示:

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

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

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

关于asp.net-mvc - 如何在 ASP.NET MVC 的 RegisterGlobalFilters 方法中进行依赖项注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39812001/

相关文章:

android - Dagger2 依赖组件与子组件

c# - Dependency Injection 和具体的依赖实现

c# - 使用 Ninject 的 Autofac InstancePerHttpRequest

asp.net-mvc - 使用存储库模式时的多个数据库上下文

asp.net-mvc - 使用 Ninject.Web.Mvc 2.0 和 ASP.NET MVC 1.0 时出现错误 "More than one matching bindings are available"

c# - 在 .NET Core 解决方案中同时拥有 API 和 MVC 项目的约定

c# - 使用 nameof() 与其父类一起检查类名以进行 MVC 验证

c# - 如何从 Excel 单元格显示值读取而不用 ClosedXML 计算公式

java - Mockito 注入(inject)嵌套 bean

javascript - 在父选项卡(页面)上显示叠加层,直到打开其所有子选项卡(页面)