所以我有了这个数据访问层,我也想登录到数据库。本着吃我自己的狗粮的精神,我想使用我的数据访问层来做日志记录。但是,我也想记录数据访问本身。像这样:
App
||
V
Log
||
V
Data=>Log
我是否有陷入反馈循环的风险?如果是这样,我应该如何避免它?项目的引用是否会相互循环并导致构建困难?您过去是如何成功地接近这种(反?)模式的?
所以我有了这个数据访问层,我也想登录到数据库。本着吃我自己的狗粮的精神,我想使用我的数据访问层来做日志记录。但是,我也想记录数据访问本身。像这样:
App
||
V
Log
||
V
Data=>Log
我是否有陷入反馈循环的风险?如果是这样,我应该如何避免它?项目的引用是否会相互循环并导致构建困难?您过去是如何成功地接近这种(反?)模式的?
创建仅包含接口的程序集(或多个程序集,视情况而定)。从您的具体类程序集中引用仅接口程序集,并让每个具体类实现一个或多个接口。没有具体类程序集是指属于您的解决方案的其他具体类程序集。
这种方法应该可以帮助您避免循环依赖。
实现控制容器的依赖注入/反转,例如StructureMap或许多其他可用的 .NET 选项之一,以进一步减少耦合。
一个可能过于简化的解决方案:
public interface ILoggable {
string ToLogFormat();
}
然后在任何可以记录的对象上实现这个接口。日志层现在只依赖于接口,可以在任何级别使用。
另一种方法是使用“帮助”类通过重载实现 ToLogFormat,例如
public class LogHelper {
public string ToLogFormat(DAO obj) { ... }
public string ToLogFormat(SomeOtherClass obj) { ... }
...
}
您可以使用一个单一的日志助手(这很糟糕,因为它必须引用每个库)但更好的解决方案可能是为每个程序集或类实现日志助手并使用自定义属性指定日志助手类的名称
就个人而言,我更喜欢 ILoggable 方法,因为它更灵活;您的日志记录包中可能有一个简单的功能,例如:
public class Logger {
public string ToLogFormat(object obj) {
if (obj is ILoggable) {
return ((ILoggable)obj).ToLogFormat();
}
return obj.ToString();
}
}