【问题标题】:How is NLog binded to ILogger with Ninject & Ninject.Extensions.LoggingNLog 如何使用 Ninject & Ninject.Extensions.Logging 绑定到 ILogger
【发布时间】:2017-03-11 09:38:50
【问题描述】:

您好,我正在尝试将 NLog 与使用 Ninject 进行依赖注入的 Web Api 2 应用程序一起使用。

到目前为止,我一直在努力寻找有关如何执行此操作的任何具体信息,我已经为 NLog 和 NLog.Configuration 安装了 NuGet 包。到目前为止,我所阅读的内容表明这些包应该可以正常工作并为我处理绑定。

我设置了 Nlog.config 文件,然后安装了 Ninject.Extensions.Logging 和 Ninject.Extensions.NLog4 包。

我正在尝试按如下方式使用 NLog

public class ErrorCheckController : ApiController
{
    private readonly ILogger _logger;

    public ErrorCheckController(ILogger logger)
    {
        _logger = logger;
    }

    public IHttpActionResult Get(string version)
    {
        try
        {
            throw new Exception("Manually thrown exception");
        }
        catch (Exception ex)
        {
            _logger.Debug(ex);
        }

        return Ok();
    }
}

在我尝试过的 NinjectWebCommon 中

  1. 无绑定
  2. kernel.Bind<ILogger>().To<Logger>(); 绑定
  3. kernel.Bind<ILogger>().ToMethod(lm => LogManager.GetLogger("MyLogger")); 绑定,其中 MyLogger 是目标配置的名称

当我执行 1 和 2 时出现错误

尝试创建类型为“ErrorCheckController”的控制器时发生错误。确保控制器有一个无参数的公共构造函数。

第三个选项获取一个记录器,但它没有使用 NLog.config 文件进行配置

编辑 这是我的配置文件

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
  autoReload="true"
  throwExceptions="false">

  <targets>
    <target xsi:type="Database" name="Ink3DPowderDbLogger" connectionStringName="MyDbContext">
      <commandText>
        INSERT INTO Log.ApiLog (
    Application,
    Logger,
    Logged,
    Level,
    Environment,
    Request,
    Message,
    BaseDir,
    Message,
    CallSite,
    CallSiteLn,
    Exception,
    EventProperties,
    StackTrace,
    ServerName,
    Port,
    Url,
    Https,
    ServerAddress,
    RemoteAddress,
    ) VALUES (
    @Application,
    @Logger,
    @Logged,
    @Level,
    @Environment,
    @Request,
    @BaseDir,
    @Message,
    @CallSite,
    @CallSiteLine,
    @Exception,
    @EventProperties,
    @StackTrace,
    @ServerName,
    @Port,
    @Url,
    @Https,
    @ServerAddress,
    @RemoteAddress,
    );
  </commandText>

  <parameter name="@application" layout="${appsetting:name=AppName:default=Unknown}" />
  <parameter name="@logger" layout="${logger}" />
  <parameter name="@logged" layout="${date}" />
  <parameter name="@level" layout="${level}" />
  <parameter name="@environment" layout="${environment}" />
  <parameter name="@request" layout="${asp-request}" />
  <parameter name="@basedir" layout="${basedir}" />
  <parameter name="@message" layout="${message}" />
  <parameter name="@callSite" layout="${callsite}" />
  <parameter name="@callSiteLine" layout="${callsite-linenumber}" />
  <parameter name="@exception" layout="${exception:tostring}" />
  <parameter name="@eventproperties" layout="${eventproperties:tostring}" />
  <parameter name="@stacktrace" layout="${stacktrace:tostring}" />
  <parameter name="@serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
  <parameter name="@port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
  <parameter name="@url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
  <parameter name="@https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
  <parameter name="@serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
  <parameter name="@remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />

</target>

  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="Ink3DPowderDbLogger" />
  </rules>
</nlog>

编辑 2 我已将我的 Get 方法更改为

public IHttpActionResult Get(string version)
    {
        IKernel kernel = new StandardKernel();
        //var resolver = new NinjectDependencyResolver(kernel);
        //var logger = (ILogger) resolver.GetService(typeof(ILogger));
        var logger = kernel.Get<ILogger>();

        try
        {
            throw new Exception("Manually thrown exception");
        }
        catch (Exception ex)
        {
            //_logger.Debug(ex);
            logger.Debug(ex);
        }

        return Ok();
    }

这给了我一个错误

没有匹配的绑定可用,并且类型不是自绑定的。

听起来好像没有任何东西绑定到 ILogger。

编辑 3

我回顾了我的配置文件,发现我告诉 NLog 静默失败。我把它关掉了,现在我得到了正确的错误。我的好像有问题

我得到错误

异常:在 NLog.Targets.DatabaseParameterInfo 上设置属性“布局”时出错

内部异常:找不到 LayoutRenderer:'appsetting'

我不太清楚为什么找不到我使用的语法与 appsetting 文档中的语法相同

【问题讨论】:

    标签: c# asp.net-web-api2 ninject nlog ninject-extensions


    【解决方案1】:

    确保控制器有一个无参数的公共构造函数。

    您收到此错误的原因是:

    1. 您没有在 Ninject 中明确配置控制器
    2. 您的配置有错误

    由于控制器没有显式注册,Ninject 会尝试为您创建它,但由于配置存在问题,它会返回 null(由 IDependencyResolver 合约规定)。

    一旦您明确注册了所有控制器(您应该始终在容器中明确注册所有根类型),Ninject 将抛出一个表达异常,解释配置错误是什么。显式注册所有根类型还允许您test your DI configuration

    【讨论】:

    • 您好,我不确定我是否关注您,.Net 中默认创建的无参数构造函数不是吗?我也一直在其他项目中使用 Ninject,而且我从来不需要显式配置控制器,但我会研究一下。我将配置文件添加到原始问题中。谢谢
    • @JeffFinn 请使用Bind&lt;ErrorCheckController&gt;().AsSelf() 注册您的ErrorCheckController。在您尝试后,我们将继续讨论:)
    • 谢谢@Steven 我已经绑定了控制器并重试了我之前的步骤。我仍然遇到同样的错误
    • @JeffFinn:你有没有可以正确解析的非默认构造函数的控制器?您可能忘记注册您的NinjectDependencyResolver。请注意,Web API 需要与 MVC 不同的依赖解析器。
    • @JeffFinn 如果您使用Get&lt;ErrorCheckController&gt;() 直接从内核解析控制器,Ninject 将抛出一个明确的异常来解释您所做的配置错误。
    【解决方案2】:

    问题最终是我试图注入

    NLog.ILogger

    而不是

    Ninject.Extensions.Logging.ILogger

    它现在正在工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多