将依赖项注入到DelegatingHandler中

13

我对依赖注入还比较陌生,但是很喜欢使用NinjectNinject.Extensions.Logging来在需要的地方[Inject]我的ILogger

然而一些DelegatingHandlers正在破坏所有的乐趣。

public class HttpsHandler : DelegatingHandler
{
    [Inject]
    public ILogger Logger { get; set; }

    protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (!string.Equals(request.RequestUri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
            {
                Logger.Info(String.Format("{0}: is using HTTP", request.RemoteAddress());
                return
                    Task.Factory.StartNew(
                        () =>
                        new HttpResponseMessage(HttpStatusCode.BadRequest)
                        {
                            Content = new StringContent("HTTPS Required")
                        });
            }

            return base.SendAsync(request, cancellationToken);
        }
 }

有没有人能指导我如何将 Ninject.Extensions.Logger.Nlog2 注入到委托处理程序中的 ILogger 中?

更新

我认为 Pete 在评论中为我指明了正确的方向(谢谢!)。 我向 HttpsHandler 添加了以下构造函数:

public HttpsHandler()
        {
            var kernel = new StandardKernel();

            var logfactory = kernel.Get<ILoggerFactory>();
            this.Logger = logfactory.GetCurrentClassLogger();
        }

现在我的记录器(Logger)可以工作了!

我唯一剩下的问题是,这样做是正确的方式,还是一种反模式(anti-pattern)?


2
谁在创建HttpsHandler实例?如果它不是由NInject创建的,那就会有问题。 - Pete
@Pete 谢谢你的回答,我觉得你让我朝着正确的方向前进了,你能否看一下我的更新问题? - Jos Vinke
1
如果您“在需要的任何地方注入[您的] ILogger”,请查看此stackoverflow q/a - Steven
@Steven 感谢这篇有趣的阅读。这是一些很好的思考食品,我肯定会加以利用,现在我只需要找出最好的方法来做到这一点。 - Jos Vinke
@JosVinke:在现有的(或遗留的)代码库中实现这些模式可能很困难,但根据我的经验,通常会得到回报(但始终一步一步地进行)。祝你好运。 - Steven
4个回答

26

DelegatingHandlers 在Web API中只会在应用程序启动时初始化一次。

这是Web API的已知问题/设计特性(我推测出于性能原因)-请参见这里的错误报告http://aspnetwebstack.codeplex.com/workitem/62

像你自己建议的构造函数初始化,只有在您具有单例类型依赖项的情况下才会起作用(这就是为什么您的记录器可以工作)。无论如何,如果您想将解析委托给Web API DependencyResolver,则必须使用GetDependencyScope(),这可以作为一种解决方法从HttpRequestMessage调用。

我之前发表了一篇关于使用Ninject做到这一点的步骤指南。您应该使用此方法来解决您的依赖关系,因为您当前的解决方案将Ninject和处理程序耦合在一起,这是不希望出现的。


谢谢,我想我已经让你的解决方案工作了(很棒的博客!),但我无法验证,因为在GetService方法中解析依赖项时出现了空引用(在c:\Projects\Ninject\ninject.extensions.logging\src\Ninject.Extensions.Logging\LoggerFactoryBase.cs的第61行)。您能否确认这是Ninject.Extensions.Logging中的错误还是我做错了什么? - Jos Vinke
GetService 就是从 kernel.Get 解析出来的。因此,您需要在应用程序启动时注册记录器 - 类似于 kernel.Bind<X>().To<Y>()。我不熟悉 ninject.extensions.logging,所以不确定如何确切地做到这一点,但它必须在应用程序启动时定义,其中您注册所有依赖项。GetDependencyScope() 只是一个快捷方式,可以从 Ninject 内核中解析出某些内容,而无需显式指定它(而不会将自己耦合到 Ninject 内核中,因为您可以轻松更改 DI 提供程序,而此代码仍将正常工作)。 - Filip W
该服务已注册,并且它也已经被LoggerFactory获取(请参见跟踪记录),即使我再次注册它,我也会得到一个异常,指出多个ILoggers已经被注册。目前,我将接受您的答案,并在有更多时间时尝试使用另一个依赖项。感谢您的帮助。 - Jos Vinke
我只是想让你知道,我又遇到了另一种情况,这个解决方案非常有用,而且非常好用,谢谢! - Jos Vinke

4

我正在使用以下内容:

 protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
 {
    var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IFooService)) as IFooService;
    // Other stuff
 }

我试图在自己的 NuGet 包内使用此功能,但它并不知道 GlobalConfiguration。我在 Microsoft.AspNet.WebApi.WebHost 包中找到了它。 - Ecyrb

1

我认为你需要的是this

这是用于MVC的Ninject依赖项解析器。然后我相信你需要使用:

GlobalConfiguration.Configuration.ServiceResolver.SetResolver()

并且传入NInject依赖解析器。


我尝试了你的解决方案,但是我真的无法弄清楚。我正在使用Asp.Net WebApi(更新标签),ServiceResolver不存在,而在Web Api中是DependencyResolver。我尝试了自定义DependencyResolver,但没有任何运气。还有其他建议吗?无论如何感谢您迄今为止的帮助。 - Jos Vinke
啊,其实我也不太清楚。你最初的标签是asp.net MVC,所以那是我知道的解决方法。抱歉。或许其他人能帮助你。 - Pete
是的,我标记它为MVC,因为它是一个MVC委托处理程序,而不是HTTP委托处理程序。就像Web Api应用程序中使用的HTTP控制器与MVC控制器一样。如果混淆它们,你将需要花费很多时间来解决问题。这就是为什么我标记了MVC,但对于造成的不便,非常抱歉并感谢您花费的时间 :) - Jos Vinke

0

我曾经遇到过类似的情况,参考了这篇文章和相关链接后,我想出了以下构造函数注入的解决方案,看起来对我来说运行良好:

using Ninject.Extensions.Logging;

公共的静态方法 注册(HttpConfiguration config) {

ILoggerFactory loggerFactory =
   config.DependencyResolver.GetService(typeof(ILoggerFactory))
   as ILoggerFactory;
config.MessageHandlers.Add(
   new HttpsHandler(loggerFactory.GetLogger(typeof(HttpsHandler))));

// Other codes ...

}

我正在使用Ninject for WebApi 2 / log4net,并已安装所有相关的NuGet包


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接