我正在用C#.NET 3.5编写一个类库程序集,用于与其他应用程序集成,包括第三方商用现成(COTS)工具。因此,有时这个类库将由我控制的应用程序(EXE)调用,而其他时候它将由我不控制的其他DLL或应用程序调用。
任何解决方案都必须:
OR
当我的独立类库被我无法控制的DLL或应用程序(例如第三方COTS工具)调用且未指定log4net配置信息时,我的类库无法执行任何操作它的记录。
如何为独立类库程序集配置和启用log4net,以便无论调用应用程序是否提供log4net配置,它都会记录?
答案 0 :(得分:12)
您可以编写XmlConfigurator类的代码:
public static class MyLogManager
{
// for illustration, you should configure this somewhere else...
private static string configFile = @"path\to\log4net.config";
public static ILog GetLogger(Type type)
{
if(log4net.LogManager.GetCurrentLoggers().Length == 0)
{
// load logger config with XmlConfigurator
log4net.Config.XmlConfigurator.Configure(configFile);
}
return LogManager.GetLogger(type);
}
}
然后在你的课程中,而不是:
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
使用:
private static readonly ILog log = MyLogManager.GetLogger(typeof(MyApp));
当然,最好将此类作为服务并使用您选择的IoC容器动态配置它,但您明白了吗?
编辑:已在评论中指出修复了Count()问题。
答案 1 :(得分:12)
第一组约束的解决方案是基本上将log4net.LogManager包装到您自己的自定义LogManager类中,如Jacob,Jeroen和McWafflestix已建议(请参阅代码如下)。
不幸的是,log4net.LogManager类是静态的,C#不支持静态继承,因此您不能简单地继承它并覆盖GetLogger方法。 然而,log4net.LogManager类中没有太多方法,所以这肯定是可能的。
这个解决方案的另一个缺点是,如果你有一个现有的代码库(我在我的情况下),你必须用你的包装类替换所有现有的log4net.LogManager调用。然而,今天的重构工具并没有什么大不了的。
对于我的项目,这些缺点超过了使用调用应用程序提供的日志记录配置的好处,因此,我选择了解决方案2.
首先,您需要一个LogManager包装类:
using System;
using System.IO;
using log4net;
using log4net.Config;
namespace MyApplication.Logging
{
//// TODO: Implement the additional GetLogger method signatures and log4net.LogManager methods that are not seen below.
public static class LogManagerWrapper
{
private static readonly string LOG_CONFIG_FILE= @"path\to\log4net.config";
public static ILog GetLogger(Type type)
{
// If no loggers have been created, load our own.
if(LogManager.GetCurrentLoggers().Length == 0)
{
LoadConfig();
}
return LogManager.GetLogger(type);
}
private void LoadConfig()
{
//// TODO: Do exception handling for File access issues and supply sane defaults if it's unavailable.
XmlConfigurator.ConfigureAndWatch(new FileInfo(LOG_CONFIG_FILE));
}
}
然后在你的课程中,而不是:
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
使用:
private static readonly ILog log = LogManagerWrapper.GetLogger(typeof(MyApp));
出于我的目的,我决定采用符合第二组约束的解决方案。请参阅下面的代码了解我的解决方案。
“程序集可以选择使用命名的日志存储库而不是默认存储库。这会将程序集的日志记录与应用程序的其余部分完全分开。这对于希望使用的组件开发人员非常有用。 log4net用于其组件,但不希望要求所有使用其组件的应用程序都知道log4net。这也意味着它们的调试配置与应用程序配置分离。程序集应指定RepositoryAttribute来设置其日志存储库。
我将以下行放在我的类库的AssemblyInfo.cs文件中:
// Log4Net configuration file location [assembly: log4net.Config.Repository("CompanyName.IntegrationLibName")] [assembly: log4net.Config.XmlConfigurator(ConfigFile = "CompanyName.IntegrationLibName.config", Watch = true)]
答案 2 :(得分:7)
在您的代码中,您可以通过
检查是否有任何记录器log4net.LogManager.GetCurrentLoggers().Count()
然后,您可以使用XmlConfigurator从文件加载默认配置:
log4net.Config.XmlConfigurator.Configure(configFile)
您可以在静态或常规构造函数中进行初始化。
class Sample
{
private static readonly log4net.ILog LOG;
static Sample()
{
if (log4net.LogManager.GetCurrentLoggers().Count() == 0)
{
loadConfig();
}
LOG = log4net.LogManager.GetLogger(typeof(Sample));
}
private static void loadConfig()
{
/* Load your config file here */
}
public void YourMethod()
{
LOG.Info("Your messages");
}
}
答案 3 :(得分:1)
在您的独立类库中,有一个使用log4net
加载log4net.Config.XmlConfigurator
配置文件的单例。
具体来说,您可以定义所有代码以使用自己的自定义日志记录类;这个类可以只是log4net日志记录调用的简单包装器,只需添加一个;创建一个静态成员,其中包含您要登录的日志信息;通过在该类的静态构造函数中调用XmlConfigurator来初始化它。这就是你所要做的一切。
答案 4 :(得分:1)
你可以在这里找到一个很好的描述: log4net: A quick start guide
如文章所述,要在每个程序集分别配置它之前,为名为AssemblyName.dll.log4net
的程序集创建一个XML文件,并将以下XML代码放入其中:
<?xml version="1.0" encoding="utf-8"?>
<log4net debug="false">
<appender name="XmlSchemaFileAppender" type="log4net.Appender.FileAppender">
<file value="AppLog.xml" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.XmlLayout" />
</appender>
<root>
<level value="WARN" />
<appender-ref ref="XmlSchemaFileAppender" />
</root>
</log4net>
它进一步描述了,要实例化一个新的记录器,只需将它声明为整个类的变量,如下所示:
public class LogSample
{
private static readonly log4net.ILog Log
= log4net.LogManager.GetLogger(typeof(LogSample));
// Class Methods Go Here...
}
然后,您可以在类中使用私有变量Log
,如:
Log.Info("Sample message");
同样,您可以使用Log.Error("Error occurred while running myMethod", ex)
记录错误以及异常详细信息。
我发现以下内容:
请勿忘记致电log4net.Config.XmlConfigurator.Configure();
以激活您的配置
如果您需要知道所写文件的路径,here一些代码如何从Log4Net获取
我希望这会有所帮助。
答案 5 :(得分:0)
这对我来说适用于共享库
protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.Assembly.GetExecutingAssembly().GetType());