#c# #asp.net-core #.net-core
#c# #asp.net-core #.net-ядро
Вопрос:
Я внедряю пользовательский ILogger в .Net Core 3.1. Класс должен реализовать следующий контракт
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
Я запускаю функцию LogDebug и передаю список аргументов кортежа (ключ, значение) следующим образом:
logger.LogDebug("MyDebugMessage", ("arg1Key", "arg2Value"), ("arg2Key", "arg2Value"), ("arg3Key", "arg3Value"));
Запускается функция журнала ILogger, и первый параметр — сообщение «MyDebugMessage» — передается в параметр состояния. Однако в функции ILogger нет переменной для списка аргументов.
Как я могу получить доступ к списку аргументов?
Комментарии:
1. Попробуйте что-то вроде этого: Список <Ключевая пара<строка, строка>> значения = новый список <Ключевая пара <строка, строка>>() { новая ключевая пара <строка, строка> («arg1Key», «arg2Value»), новая ключевая пара <строка, строка> («arg2Key», «arg2Value»), new KeyValuePair<строка,строка>(«arg3Key», «arg3Value») }; строковое сообщение = строка. Join(«;», значения. Выберите(x => строка. Формат(«{0},{1}», x.Ключ, x.Значение)));
2. Спасибо @jdweng за ваш ответ. Как я могу получить доступ к значениям внутри общедоступного метода void Log<TState> ?
3. Результаты работы регистратора помещаются в файл.
4. Я использую пользовательский регистратор, поэтому я реализовал метод ILogger внутри пользовательского класса. Когда происходит ведение журнала, этот метод вызывается внутри пользовательского регистратора. Но я не могу получить доступ к переданным значениям. Следовательно, мой вопрос в том, как я могу получить доступ к переданным значениям внутри пользовательского класса.
5. Это словарь. См . : learn.microsoft.com/en-us/aspnet/core/fundamentals/logging /…
Ответ №1:
До сих пор я обнаружил, что единственный способ — использовать отражение, чтобы получить закрытый член _values состояния TState.
public class ApiLogger : ILogger
{
// more code
public async void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
FieldInfo[] fieldsInfo = state.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo props = fieldsInfo.FirstOrDefault(o => o.Name == "_values");
object[] values = (object[])props?.GetValue(state);
// more code
}
// more code
}
Ответ №2:
Объектом по умолчанию, переданным в «состояние TState», является Microsoft.Расширения.Ведение журнала.Formattedlog values
который является производным от типа IReadOnlyList<KeyValuePair<строка, объект>>
из него можно получить список аргументов kvp
Ответ №3:
Хак с отражением, описанный Хьюго, больше не работает в .net core 7
Я думаю, что ‘params object[]? параметр args никогда не предназначался для передачи дополнительных данных вашему ILogger.Реализация журнала, но предназначена только для форматирования сообщения.
Поэтому я придумал альтернативное решение.
Я использую параметр EventID, который я обычно не использую. EventID — это объект с идентификатором int и свойством string Name . Это свойство Name может быть заполнено любой строкой, которая вам нравится. Я просто создаю типизированный объект и сериализую его в json. Создайте экземпляр класса EventID с нерелевантным свойством Id и именем, присвоенным my json.
В вашем ILogger.Реализация журнала Я просто десериализую идентификатор события.Назовите его типизированный класс, и я ввел доступ к данным, которые я хочу передать.
Вы могли бы использовать свойство Id, чтобы сообщить принимающей стороне, какой объект можно десериализовать из свойства Name . Таким образом, вы можете передавать серверные типы объектов.
Комментарии:
1. Согласен, я думал о том же и реализовал с использованием EventID . Спасибо!