#c# #asp.net-core #.net-core
#c# #asp.net-core #.net-core
Вопрос:
Рассмотрим следующую структуру проекта для веб-проекта .NET Core.
Мое приложение.Проект пользовательского интерфейса (MVC) вызывает MyApp.BusinessRules вызывает MyApp.ServiceLayer вызывает MyApp.DbAccess проект вызывает что угодно.
Во внешнем проекте (MyApp.Пользовательский интерфейс), я определил logger
. Я хотел бы получить доступ к этому экземпляру logger
в проекте MyApp.DbAccess (или любом нисходящем проекте), не передавая его через параметры из действий контроллера. Я также не могу выполнить внедрение зависимостей так глубоко в структуру.
Итак, как получить доступ к регистратору?
Комментарии:
1. Logger должен быть определен в проекте более низкого уровня, чем пользовательский интерфейс, в противном случае все остальные ваши уровни имеют прямую или косвенную зависимость от уровня пользовательского интерфейса, что не идеально. Вы можете создать другую библиотеку, скажем
MyApp.Common
, и переместить регистратор туда.2. Что такое »
logger
«? Это что-то ваше собственное создание или вы используетеMicrosoft.Extensions.Logging
фасад?3. @ChrisPratt Да, Microsoft. Расширения. В основном, фабрика регистратора регистрации. В частности, с Serilog в качестве поставщика.
4. Почему вы не можете использовать внедрение зависимостей для своей логики доступа к БД? Если вы введете
ILogger<T>
в конструктор службы БД (даже если это одноэлементный), то регистратор позаботится о областях ведения журнала — ASP.NET Ядро настроит область ведения журнала для каждого запроса.5. @Sam Вот что я в итоге сделал. Пока работает хорошо.
Ответ №1:
Регистратор не должен быть определен на уровне пользовательского интерфейса. Это сквозная проблема, поэтому вы должны определить ее во внешней библиотеке и ссылаться на то, что во всех проектах вам требуется ведение журнала.
Если вы хотите регистрировать только исключения, вы могли бы определить глобальный обработчик исключений, позволить исключениям всплывать на уровень пользовательского интерфейса и регистрировать их там. Пример здесь
В случае, если вы действительно хотите полностью передать свой регистратор, вы можете использовать Action
в качестве параметра в методах и передать лямбда-выражение с вызовом метода, который вы хотите вызвать ниже по потоку.
public class Logger
{
public string Message { get; set; }
public void Log(string message)
{
Message = message;
}
}
public class Business
{
public void DoWork(int id, Action<string> logAction)
{
if (id < 0)
{
logAction("The string is less than zero");
}
}
}
Вызывающий код
Logger logger = new Logger();
Business business = new Business();
business.DoWork(-1, (message) => logger.Log(message));
Комментарии:
1. Регистратор определен в Startup.cs и привязан к веб-хостингу. Это не только для обработки исключений, но и для отслеживания.
2. @AngryHacker только что обновил мой ответ — вы можете определить лямбда-выражение и передать его своим нисходящим методам:
Action<string> loggingAction = (message) => logger.Log(message);
3. И каков список параметров
DoWork
? Это (int, Func)?4. В моем примере это подпись
void DoWork(int id, Action<string> logAction)
— у нее есть int и лямбда для ведения журнала