我应该直接在我的域模型对象中使用log4net吗?

问题描述:

我想知道是否在我的域对象上直接使用log4net是不好的做法......我将在ASP.NET MVC应用程序端使用ELMAH作为例外,但出于一些信息的目的,我想记录有关域模型本身的一些数据。我应该直接在我的域模型对象中使用log4net吗?

鉴于以下域对象:

public class Buyer 
{ 
    private int _ID; 
    public int ID 
    { 
     get { return _ID; } 
     set 
     { 
      _ID = value; 
     } 
    } 

    private IList<SupportTicket> _SupportTickets=new List<SupportTicket>(); 
    public IList<SupportTicket> SupportTickets 
    { 
     get 
     { 
      return _SupportTickets.ToList<SupportTicket>().AsReadOnly(); 
     } 
    } 

    public void AddSupportTicket(SupportTicket ticket) 
    { 
     if (!SupportTickets.Contains(ticket)) 
     { 
      _SupportTickets.Add(ticket); 
     } 
    } 
} 

是在AddSupportTicketMethod添加日志的行为是一个坏主意...所以essentialy它会是这样的:

 public class Buyer 
{ 
    protected static readonly ILog log = LogManager.GetLogger(typeof(SupportTicket)); 

    public Buyer() 
    { 
     log4net.Config.XmlConfigurator.Configure(); 
    } 


    private int _ID; 
    public int ID 
    { 
     get { return _ID; } 
     set 
     { 
      _ID = value; 
     } 
    } 

    private IList<SupportTicket> _SupportTickets=new List<SupportTicket>(); 
    public IList<SupportTicket> SupportTickets 
    { 
     get 
     { 
      return _SupportTickets.ToList<SupportTicket>().AsReadOnly(); 
     } 
    } 

    public void AddSupportTicket(SupportTicket ticket) 
    { 
     if (!SupportTickets.Contains(ticket)) 
     { 
      _SupportTickets.Add(ticket); 
     } else { 
      log.Warn("Duplicate Ticket Not Added."); 
     } 
    } 
} 

如果你打算从你的域对象登录,并且你使用了一个你可能想要换出的IOC容器,我会建议你使用Service Locator模式(你可以看看Sharp#架构的一个很好的SafeServiceLocator实现,它包含了msoft的ServiceLocator和更多信息错误消息)。

我还想建议您考虑是否要记录您在示例中显示的错误类型。我倾向于希望在这种情况下让域对象抛出异常,并让调用者决定这是否是应用程序期望的东西(因此不应该被记录)或者是否表示调用者想要的情况以某种方式处理。

+3

服务定位器是一种反模式,并且破坏了依赖注入的目的。这个答案不是主观错误的,它是客观错误的。 – jason 2011-02-13 17:18:57

这是一个经典题!

这样做的好方法是引入一个ILogger类型的类成员并将日志记录抽象到此接口中。在你的课上,无论你做什么,都可以通过这个界面进行调用。然后使用可用的IoC容器或依赖注入farmeworks之一在运行时注入此依赖项。默认情况下,你可以使用这个接口的log4net实现。

这里是可用的依赖注入框架的一个长长的清单: http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx

我想记录是一个横切关注点,所以最好在面向方面的方式进行。如果您使用的是像Spring.NET这样的框架,那么您可以使用它。

我在域对象中直接使用了log4net和log4J。这有很好的副作用和坏的。

  • +:登录域对象是简单明了的代码,你知道你可以采取的log4net的功能。
  • -:这意味着该程序利用域对象的需要注意的log4net的配置,这可能会或可能不会是一个问题
  • -:你不能域对象链接到不同于调用程序正在使用的log4net版本。我看到很多与log4net 1.2.0.10链接的项目和另一个与早期版本链接的项目有冲突。

不记录在你的域对象是一个坏主意。另一种方法就像其他人所说的那样,依赖注入或外部框架(例如log4J的commons-logging)允许插入不同的日志框架或创建一个接口来执行日志记录和针对该接口的日志记录。 (使用你的域对象的代码将需要为记录目的提供该接口的适当实例。)