我有一个具有以下不同层的web api解决方案。我喜欢在我的项目中实现统一log4net扩展,并希望在不同的层中使用它。
- DL
- BL
- Web(包含控制器类并使用Unity for IOC(
我需要只在作为主要入口的web层安装log4net包吗?还是应该安装在所有层中?
只有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
}
业务层不需要引用外部依赖项,因为它也只依赖于自定义抽象。
在最高级别,Web项目。再次假设一个简单的控制器
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作为整个系统的日志实现,以便Web项目引用必要的依赖项,然后创建
public class Log4NetWrapper : ILogger {
private readonly ILog log; //log4net
public Log4NetWrapper(ILog log) {
this.log = log;
}
public void LogMessage(string msg) {
log.Info(msg);
}
//...
}
在这一点上,只有Web项目需要引用第三方依赖关系。
现在,任何时候一个依赖类想要使用日志记录,都可以通过log4net来完成。
很好,在Web项目的组合根中,您可以注册抽象和实现以及使用log4net所需的任何扩展。
container = new UnityContainer();
container.AddNewExtension<Log4NetExtension>();
container.RegisterType<ILogger, Log4NetWrapper>(new HierarchicalLifetimeManager());
因此,现在,当需要从容器中解析ExampleController
时,Log4NetWrapper
将被注入到当前正在Web项目中执行的整个对象图中。
在这种情况下,log4net是一个实现问题。由于上面的设计,所有涉及的类都只关心抽象,而不关心具体化。
长话短说,
我需要只在主要入口的web层安装log4net包吗?
是
还是应该在所有层中安装它?
如果您的体系结构设计得很干净,那么否。
在整个示例中都使用DI。当设计正确时,只有组合根需要知道任何外部依赖关系。