Как 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 я пытался
- Без привязки
- Связывание с
kernel.Bind<ILogger>().To<Logger>();
- Связывание с
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
Это работает сейчас.
Убедитесь, что у контроллера есть открытый конструктор без параметров.
Причина, по которой вы получаете эту ошибку, заключается в следующем:
- вы не настроили свой контроллер явно в Ninject
- В вашей конфигурации произошла ошибка
Поскольку для контроллера нет явной регистрации, Ninject попытается создать его для вас, но, поскольку в конфигурации есть проблема, он вернется. null
(что продиктовано IDependencyResolver
контракт).
Как только вы зарегистрируете все свои контроллеры явно (вы всегда должны явно регистрировать все ваши корневые типы в контейнере), Ninject сгенерирует выразительное исключение, объясняющее, что является ошибкой конфигурации. Явная регистрация всех корневых типов также позволяет протестировать конфигурацию DI.