Как NLog привязывается к ILogger с помощью Ninject & Ninject.Extensions.Logging

Привет, я пытаюсь использовать NLog с приложением Web Api 2, которое использует Ninject для внедрения зависимостей.

Я изо всех сил пытался найти конкретную информацию о том, как это сделать, до сих пор я установил пакеты NuGet для NLog & NLog.Configuration. Пока то, что я прочитал, говорит о том, что эти пакеты должны просто работать и позаботиться о связывании для меня.

Я настроил файл 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". Убедитесь, что у контроллера есть открытый конструктор без параметров.

Третий вариант получает Logger, но он не настроен с использованием файла 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 Я изменил свой метод получения на

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 молчать. Я выключил это, и теперь я получаю правильные ошибки. Кажется, есть проблема с моим

Я получаю ошибки

Исключение: ошибка при установке свойства 'Layout' в NLog.Targets.DatabaseParameterInfo

Внутреннее исключение: LayoutRenderer не может быть найден: 'appsetting'

Я не слишком уверен, почему это не может быть найдено, я использую тот же синтаксис, что и в документации для установки приложений

2 ответа

Решение

Проблема закончилась тем, что я пытался ввести

NLog.ILogger

вместо

Ninject.Extensions.Logging.ILogger

Это работает сейчас.

Убедитесь, что у контроллера есть открытый конструктор без параметров.

Причина, по которой вы получаете эту ошибку, заключается в следующем:

  1. вы не настроили свой контроллер явно в Ninject
  2. В вашей конфигурации произошла ошибка

Поскольку для контроллера нет явной регистрации, Ninject попытается создать его для вас, но, поскольку в конфигурации есть проблема, он вернется. null (что продиктовано IDependencyResolver контракт).

Как только вы зарегистрируете все свои контроллеры явно (вы всегда должны явно регистрировать все ваши корневые типы в контейнере), Ninject сгенерирует выразительное исключение, объясняющее, что является ошибкой конфигурации. Явная регистрация всех корневых типов также позволяет протестировать конфигурацию DI.

Другие вопросы по тегам