C# 如何为独立的类库程序集配置和启用 log4net?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1028375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you configure and enable log4net for a stand-alone class library assembly?
提问by Zach Burlingame
Background
背景
I am writing a class library assembly in C# .NET 3.5 which is used for integration with other applications including third-party Commercial-Off-The-Shelf (COTS) tools. Therefore, sometimes this class library will be called by applications (EXEs) that I control while other times it will be called by other DLLs or applications that I do notcontrol.
我正在用 C# .NET 3.5 编写一个类库程序集,用于与其他应用程序集成,包括第三方商业现货 (COTS) 工具。因此,有时这个类库会被我控制的应用程序 (EXE) 调用,而有时它会被我无法控制的其他 DLL 或应用程序调用。
Assumptions
假设
- I am using C# 3.0, .NET 3.5 SP1, and Visual Studio 2008 SP1
- I am using log4net 1.2.10.0 or greater
- 我使用的是 C# 3.0、.NET 3.5 SP1 和 Visual Studio 2008 SP1
- 我使用的是 log4net 1.2.10.0 或更高版本
Constraints
约束
Any solution must:
任何解决方案都必须:
- Allow for the class library to enable and configure logging via it's own configuration file, if the calling application does not configure log4net.
- Allow for the class library to enable and configuring logging via the calling applications configuration, if it specifies log4net information
- 如果调用应用程序未配置 log4net,则允许类库通过其自己的配置文件启用和配置日志记录。
- 允许类库通过调用应用程序配置启用和配置日志记录,如果它指定了 log4net 信息
OR
或者
- Allow for the class library to enable and configuring logging using it's own configuration file at all times.
- 允许类库始终使用自己的配置文件启用和配置日志记录。
Problem
问题
When my stand-alone class library is called by a DLL or application that I do not control (such as a third-party COTS tool) and which doesn't specify log4net configuration information, my class library is unable to do any of it's logging.
当我的独立类库被我无法控制的 DLL 或应用程序(例如第三方 COTS 工具)调用且未指定 log4net 配置信息时,我的类库无法执行任何日志记录.
Question
题
How do you configure and enable log4net for a stand-alone class library assembly so that it will log regardless if the calling application provides log4net configuration?
您如何为独立类库程序集配置和启用 log4net,以便无论调用应用程序是否提供 log4net 配置,它都会记录日志?
采纳答案by Zach Burlingame
Solution 1
解决方案1
A solution for the first set of constraints is to basically wrap the log4net.LogManagerinto your own custom LogManager class like Jacob, Jeroen, and McWafflestixhave suggested (see code below).
第一组约束的解决方案基本上是将log4net.LogManager包装到您自己的自定义 LogManager 类中,如Jacob、Jeroen和McWafflestix所建议的(参见下面的代码)。
Unfortunately, the log4net.LogManagerclass is static and C# doesn't support static inheritance, so you couldn't simply inherit from it and override the GetLogger method. There aren't too many methods in the log4net.LogManagerclass however, so this is certainly a possibility.
不幸的是,log4net.LogManager类是静态的,C# 不支持静态继承,因此您不能简单地从它继承并覆盖 GetLogger 方法。然而,在log4net.LogManager类中没有太多方法,所以这当然是可能的。
The other drawback to this solution is that if you have an existing codebase (which I do in my case) you would have to replace all existing calls to log4net.LogManager with your wrapper class. Not a big deal with today's refactoring tools however.
这个解决方案的另一个缺点是,如果你有一个现有的代码库(我在我的例子中是这样做的),你必须用你的包装类替换对 log4net.LogManager 的所有现有调用。然而,对于今天的重构工具来说,这没什么大不了的。
For my project, these drawbacks outweighed the benefits of using a logging configuration supplied by the calling application so, I went with Solution 2.
对于我的项目,这些缺点超过了使用调用应用程序提供的日志配置的好处,因此,我采用了解决方案 2。
Code
代码
First, you need a LogManager wrapper class:
首先,您需要一个 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));
}
}
Then in your classes, instead of:
然后在您的课程中,而不是:
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
Use:
用:
private static readonly ILog log = LogManagerWrapper.GetLogger(typeof(MyApp));
Solution 2
解决方案2
For my purposes, I have decided to settle on a solution that meets the second set of constraints. See the code below for my solution.
出于我的目的,我决定采用满足第二组约束的解决方案。请参阅下面的代码以了解我的解决方案。
From the Apache log4net document:
"An assembly may choose to utilize a named logging repository rather than the default repository. This completely separates the logging for the assembly from the rest of the application. This can be very useful to component developers that wish to use log4net for their components but do not want to require that all the applications that use their component are aware of log4net. It also means that their debugging configuration is separated from the applications configuration. The assembly should specify the RepositoryAttribute to set its logging repository."
“程序集可以选择使用命名的日志记录存储库而不是默认存储库。这将程序集的日志记录与应用程序的其余部分完全分开。这对于希望将 log4net 用于其组件但不这样做的组件开发人员非常有用不想要求使用其组件的所有应用程序都知道 log4net。这也意味着它们的调试配置与应用程序配置分开。程序集应指定 RepositoryAttribute 来设置其日志记录存储库。”
Code
代码
I placed the following lines in the AssemblyInfo.cs file of my class library:
我在我的类库的 AssemblyInfo.cs 文件中放置了以下几行:
// Log4Net configuration file location [assembly: log4net.Config.Repository("CompanyName.IntegrationLibName")] [assembly: log4net.Config.XmlConfigurator(ConfigFile = "CompanyName.IntegrationLibName.config", Watch = true)]
// Log4Net configuration file location [assembly: log4net.Config.Repository("CompanyName.IntegrationLibName")] [assembly: log4net.Config.XmlConfigurator(ConfigFile = "CompanyName.IntegrationLibName.config", Watch = true)]
? ??
? ??
References
参考
回答by Paul Sonier
In your standalone class library, have a singleton which loads the log4net
configuration file using the log4net.Config.XmlConfigurator
.
在您的独立类库中,有一个log4net
使用log4net.Config.XmlConfigurator
.
Specifically, you can define all of your code to use your own custom logging class; this class can just be a simple wrapper of the log4net logging calls, with one addition; make a static member which contains the log information you want to log to; initialize that with a call to the XmlConfigurator in the static constructor for that class. That's all you have to do.
具体来说,您可以定义所有代码以使用您自己的自定义日志记录类;此类可以只是 log4net 日志记录调用的简单包装器,并添加一个;创建一个静态成员,其中包含您要登录的日志信息;通过在该类的静态构造函数中调用 XmlConfigurator 来初始化它。这就是你所要做的。
回答by Jacob
You can probably code something around the XmlConfiguratorclass:
您可能可以围绕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);
}
}
Then in your classes, instead of:
然后在您的课程中,而不是:
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
Use:
用:
private static readonly ILog log = MyLogManager.GetLogger(typeof(MyApp));
Of course, it would be preferable to make this class a service and dynamically configure it with the IoC container of your choice, but you get the idea?
当然,最好将此类设为服务并使用您选择的 IoC 容器对其进行动态配置,但是您明白了吗?
EDIT:Fixed Count() problem pointed out in comments.
编辑:修复了评论中指出的 Count() 问题。
回答by Jeroen Huinink
In your code you can check if there are any loggers via
在您的代码中,您可以通过以下方式检查是否有任何记录器
log4net.LogManager.GetCurrentLoggers().Count()
You could then for example use an XmlConfigurator to load a default configuration from a file:
例如,您可以使用 XmlConfigurator 从文件加载默认配置:
log4net.Config.XmlConfigurator.Configure(configFile)
You could do the initialization in a static or regular constructor.
您可以在静态或常规构造函数中进行初始化。
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");
}
}
回答by Matt
You can find a good description here: log4net: A quick start guide
你可以在这里找到一个很好的描述: log4net:快速入门指南
As the article describes, to configure it fore each assembly separately, create an XML file for your assembly named AssemblyName.dll.log4net
and place the following XML code into it:
正如文章所述,要分别为每个程序集配置它,请为您的程序集创建一个 XML 文件AssemblyName.dll.log4net
,并将以下 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>
It further describes, to instantiate a new logger, simply declare it as a variable for the entire class as follows:
它还进一步描述,要实例化一个新的记录器,只需将其声明为整个类的变量,如下所示:
public class LogSample
{
private static readonly log4net.ILog Log
= log4net.LogManager.GetLogger(typeof(LogSample));
// Class Methods Go Here...
}
You can then use the private variable Log
inside your class like:
然后,您可以Log
在类中使用私有变量,例如:
Log.Info("Sample message");
Likewise you can use Log.Error("Error occurred while running myMethod", ex)
to log errors along with the exception details.
同样,您可以使用Log.Error("Error occurred while running myMethod", ex)
记录错误以及异常详细信息。
What I found is the following:
我发现的是以下内容:
Don't forget to call
log4net.Config.XmlConfigurator.Configure();
to activate your configurationIf you need to know the path of the file(s) written, heresome code how to obtain it from Log4Net
不要忘记打电话
log4net.Config.XmlConfigurator.Configure();
激活您的配置如果您需要知道写入的文件的路径,这里有一些代码如何从 Log4Net 获取它
I hope this helps.
我希望这有帮助。
回答by Brian5003
This works for me for a shared library
这适用于我的共享库
protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.Assembly.GetExecutingAssembly().GetType());