我对于使用 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/