Design patterns Log4Net包装器类是什么样子的?
我一直在寻找.net(c#)的日志框架,在阅读了stackoverflow上的几个问答线程之后,我决定尝试一下log4net。我看到人们一次又一次地提到他们为log4net使用了一个包装器类,我想知道那会是什么样子 我将代码分为不同的项目(数据访问/业务/Web服务/)。 log4net包装器类是什么样子的?包装器类是否需要包含在所有项目中?我应该把它作为一个单独的项目一起构建吗Design patterns Log4Net包装器类是什么样子的?,design-patterns,log4net,Design Patterns,Log4net,我一直在寻找.net(c#)的日志框架,在阅读了stackoverflow上的几个问答线程之后,我决定尝试一下log4net。我看到人们一次又一次地提到他们为log4net使用了一个包装器类,我想知道那会是什么样子 我将代码分为不同的项目(数据访问/业务/Web服务/)。 log4net包装器类是什么样子的?包装器类是否需要包含在所有项目中?我应该把它作为一个单独的项目一起构建吗 包装器应该是单例类吗 我的理解是log4net的包装类是一个静态类,负责从app.config/web.config
包装器应该是单例类吗 我的理解是log4net的包装类是一个静态类,负责从app.config/web.config或通过代码初始化日志对象(例如与NUnit集成).log4net包装器的一个可能用途是通过反射获取调用类和方法的类,以了解日志条目发生的位置。至少我经常使用它。本质上,您创建了一个接口,然后是该接口的一个具体实现,它直接封装了Log4net的类和方法。可以通过创建更具体的类来包装其他日志记录系统,这些类可以包装这些系统的其他类和方法。最后,使用工厂根据配置设置或代码行更改创建包装器的实例。(注意:使用容器(例如)可以获得更灵活、更复杂的功能。) 以及在类中使用此代码的示例(声明为静态只读字段): 您可以使用以下方法获得同样的性能友好效果:
private static readonly ILogger _logger =
LogManager.GetLogger(typeof(YourTypeName));
前一个示例被认为更易于维护
您不希望创建一个单例来处理所有日志记录,因为Log4Net记录调用类型;让每种类型都使用自己的记录器,而不是在日志文件中只看到一种类型报告所有消息,这会更干净、更有用
因为您的实现应该是相当可重用的(组织中的其他项目),所以您可以将其作为自己的程序集,或者理想情况下将其包含在您自己的个人/组织的框架/实用程序集中。不要在每个业务/数据/UI程序集中分别重新声明这些类,因为它们是不可维护的。为log4net编写包装器有什么好处。我建议先熟悉log4net类,然后再编写它们的包装器。cfeduke关于如何编写所述包装器的回答是正确的,但除非您需要在他的示例中添加实际功能,否则包装器只会成功地减慢日志记录过程,并为未来的维护人员增加复杂性。当.Net中可用的重构工具使这些更改变得非常简单时,尤其如此。假设您使用类似的工具,您还可以向日志管理器添加重载,如下所示:
public static ILogger GetLogger()
{
var stack = new StackTrace();
var frame = stack.GetFrame(1);
return new Log4NetWrapper(frame.GetMethod().DeclaringType);
}
这样,您现在就可以在代码中使用:
private static readonly ILogger _logger = LogManager.GetLogger();
而不是以下任何一项:
private static readonly ILogger _logger =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILogger _logger =
LogManager.GetLogger(typeof(YourTypeName));
这实际上相当于第一个备选方案(即使用
MethodBase.GetCurrentMethod().DeclaringType
),只是简单一点。Alconja,我喜欢您使用stacktrace跳回调用方法的想法。我正在考虑进一步封装调用,不仅要检索logger对象,还要实际执行日志记录。我想要的是一个静态类,通过从使用的特定实现中抽象来处理日志记录。即
LoggingService.LogError("my error message");
这样,如果我以后决定使用另一个日志系统,我只需要更改静态类的内部结构
因此,我利用您的想法使用堆栈跟踪获取调用对象:
public static class LoggingService
{
private static ILog GetLogger()
{
var stack = new StackTrace();
var frame = stack.GetFrame(2);
return log4net.LogManager.GetLogger(frame.GetMethod().DeclaringType);
}
public static void LogError(string message)
{
ILog logger = GetLogger();
if (logger.IsErrorEnabled)
logger.Error(message);
}
...
}
有人认为这种方法有问题吗?我知道这个答案已经晚了,但它可能会对将来的人有所帮助 听起来您需要XQuiSoft日志提供的编程API。您不必指定要使用XQuiSoft的记录器。就这么简单: Log.Write(Level.Verbose,“source”,“category”,“此处的消息”) 然后通过配置,您可以按来源、类别、级别或任何其他自定义筛选器将消息定向到不同的位置(文件、电子邮件等)
请参阅以获取介绍。我已成功地将log4net依赖项隔离到单个项目中。如果您也打算这样做,下面是我的包装器类的外观:
using System;
namespace Framework.Logging
{
public class Logger
{
private readonly log4net.ILog _log;
public Logger()
{
_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
public Logger(string name)
{
_log = log4net.LogManager.GetLogger(name);
}
public Logger(Type type)
{
_log = log4net.LogManager.GetLogger(type);
}
public void Debug(object message, Exception ex = null)
{
if (_log.IsDebugEnabled)
{
if (ex == null)
{
_log.Debug(message);
}
else
{
_log.Debug(message, ex);
}
}
}
public void Info(object message, Exception ex = null)
{
if (_log.IsInfoEnabled)
{
if (ex == null)
{
_log.Info(message);
}
else
{
_log.Info(message, ex);
}
}
}
public void Warn(object message, Exception ex = null)
{
if (_log.IsWarnEnabled)
{
if (ex == null)
{
_log.Warn(message);
}
else
{
_log.Warn(message, ex);
}
}
}
public void Error(object message, Exception ex = null)
{
if (_log.IsErrorEnabled)
{
if (ex == null)
{
_log.Error(message);
}
else
{
_log.Error(message, ex);
}
}
}
public void Fatal(object message, Exception ex = null)
{
if (_log.IsFatalEnabled)
{
if (ex == null)
{
_log.Fatal(message);
}
else
{
_log.Fatal(message, ex);
}
}
}
}
}
别忘了在接口项目的AssemblyInfo.cs
中添加这个(我花了好几个小时才找到这个)
并将log4net配置xml放入
log4net.config
文件中,将其设置为Content
,Copy Always
有一些类似的框架,它们促进了对您选择的日志框架使用a
这是一个使用以下内容的示例:
使用系统;
使用log4net;
使用log4net.Core;
使用棱镜测井;
公共类Log4NetLoggerFacade:ILoggerFacade
{
私有静态只读ILog Log4NetLog=LogManager.GetLogger(typeof(Log4NetLoggerFacade));
公共作废日志(字符串消息、类别、优先级)
{
开关(类别)
{
案例类别。调试:
Log4NetLog.Logger.Log(typeof(Log4NetLoggerFacade),Level.Debug,message,null);
打破
案件类别.例外情况:
Log4NetLog.Logger.Log(typeof(Log4NetLoggerFacade),Level.Error,message,null);
打破
案件类别。信息:
Log4NetLog.Logger.Log(typeof(Log4NetLoggerFacade),Level.Info,message,null);
打破
案例类别。警告:
Log4NetLog.Logger.Log(typeof(Log4NetLoggerFacade),Level.Warn,message,null);
打破
违约:
抛出新ArgumentOutOfRangeException(nameof(category),category,null);
public static class LoggingService
{
private static ILog GetLogger()
{
var stack = new StackTrace();
var frame = stack.GetFrame(2);
return log4net.LogManager.GetLogger(frame.GetMethod().DeclaringType);
}
public static void LogError(string message)
{
ILog logger = GetLogger();
if (logger.IsErrorEnabled)
logger.Error(message);
}
...
}
using System;
namespace Framework.Logging
{
public class Logger
{
private readonly log4net.ILog _log;
public Logger()
{
_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
public Logger(string name)
{
_log = log4net.LogManager.GetLogger(name);
}
public Logger(Type type)
{
_log = log4net.LogManager.GetLogger(type);
}
public void Debug(object message, Exception ex = null)
{
if (_log.IsDebugEnabled)
{
if (ex == null)
{
_log.Debug(message);
}
else
{
_log.Debug(message, ex);
}
}
}
public void Info(object message, Exception ex = null)
{
if (_log.IsInfoEnabled)
{
if (ex == null)
{
_log.Info(message);
}
else
{
_log.Info(message, ex);
}
}
}
public void Warn(object message, Exception ex = null)
{
if (_log.IsWarnEnabled)
{
if (ex == null)
{
_log.Warn(message);
}
else
{
_log.Warn(message, ex);
}
}
}
public void Error(object message, Exception ex = null)
{
if (_log.IsErrorEnabled)
{
if (ex == null)
{
_log.Error(message);
}
else
{
_log.Error(message, ex);
}
}
}
public void Fatal(object message, Exception ex = null)
{
if (_log.IsFatalEnabled)
{
if (ex == null)
{
_log.Fatal(message);
}
else
{
_log.Fatal(message, ex);
}
}
}
}
}
[assembly: log4net.Config.XmlConfigurator(Watch = true, ConfigFile = "log4net.config")]