Только Web (точка входа в приложение) действительно должна ссылаться на зависимость третьей части
Как я объясняю в одном из ваших предыдущих вопросов.
Создайте основной проект для своего пользовательского регистратора
public interface ILogger {
//...
}
Все остальные проекты будут ссылаться на этот проект кода и использовать абстракцию ведения журнала.
Например, следующее находится на уровне данных
public class ExampleRepository : IRepository {
private readonly ILogger logger;
public ExampleRepository(ILogger logger){
this.logger = logger;
}
//...use logger
}
Слой данных не должен ссылаться на внешнюю зависимость, поскольку он опирается только на пользовательскую абстракцию.
Далее, скажем, бизнес-уровень имеет следующий сервис
public class ExampleService: IService {
private readonly ILogger logger;
private readonly IRepository repository;
public ExampleService(IRepository repository, ILogger logger){
this.logger = logger;
this.repository = repository;
}
//...use logger and repository
}
Бизнес-уровню не нужно ссылаться на внешнюю зависимость, поскольку он также опирается только на пользовательские абстракции.
На высшем уровне веб-проект. Опять предполагая простой контроллер
public class ExampleController: Controller {
private readonly ILogger logger;
private readonly IService service;
public ExampleController(IService service, ILogger logger){
this.logger = logger;
this.service = service;
}
//...use logger and service
}
Во всем этом примере все классы зависят от абстракций, а не от проблем реализации.
Вы хотите использовать log4net в качестве реализации ведения журнала для всей системы, чтобы веб-проект ссылался на необходимые зависимости и затем создавал
public class Log4NetWrapper : ILogger {
private readonly ILog log; //log4net
public Log4NetWrapper(ILog log) {
this.log = log;
}
public void LogMessage(string msg) {
log.Info(msg);
}
//...
}
На данный момент только веб-проект должен ссылаться на стороннюю зависимость.
Теперь каждый раз, когда зависимый класс хочет использовать ведение журнала, это должно быть сделано через log4net.
Отлично, в корне композиции веб-проекта вы регистрируете абстракцию и реализацию вместе со всеми расширениями, необходимыми для использования log4net.
container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
container.RegisterType<ILogger, Log4NetWrapper>(new HierarchicalLifetimeManager());
Так что теперь, когда когда-либо потребуется ExampleController
из контейнера, Log4NetWrapper
будет внедрен во весь граф объектов, который в данный момент выполняется в веб-проекте.
В этом сценарии log4net является проблемой реализации. Из-за вышеупомянутого дизайна все участвующие классы связаны только с абстракциями, а не с конкрецией.
Короче говоря,
Нужно ли устанавливать пакет log4net только в веб-слое, который является главной точкой входа?
YES
или он должен быть установлен во всех слоях?
Если ваша архитектура разработана правильно, то НЕТ .
DI используется на протяжении всего этого примера. При правильном проектировании только корень композиции должен знать о любых внешних зависимостях.