简体   繁体   English

从自定义界面记录Log4Net

[英]Log4Net logging from custom interface

I would like to know how to print the right class name in the %logger pattern using log4net (in my example). 我想知道如何使用log4net(在我的示例中)在%logger模式中打印正确的类名。

In my app I am using a logging class implementing a logging interface (following SOLID). 在我的应用程序中,我正在使用实现日志记录接口的日志记录类(在SOLID之后)。 Other classes use the logging interface abstraction to perform the actual logging. 其他类使用日志记录接口抽象来执行实际的日志记录。 I want to switch to Log4Net, but I was thinking of keeping the logging abstraction. 我想切换到Log4Net,但是我正在考虑保留日志记录抽象。 The custom logging class methods take objects as arguments and create logs basing on their states. 自定义日志记录类方法将对象作为参数并根据其状态创建日志。

So in the below example the %logger pattern will log "MyLogger", which is expected, but I would like to log the calling class name (in this case ObjectManipulator). 因此,在下面的示例中,%logger模式将记录“ MyLogger”,这是预期的,但是我想记录调用类的名称(在本例中为ObjectManipulator)。

using System.Reflection;
using log4net;

namespace LoggingTestur
{
    class Program
    {
        class AnObject
        {
            public string State { get; set; }
        }

        interface IMyLogger
        {
            void LogObjectStateChenge(AnObject anObject);
        }

        class MyLogger : IMyLogger
        {
            private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

            public void LogObjectStateChenge(AnObject anObject)
            {
                Log.InfoFormat("AnObject's state is: {0}", anObject.State);
            }
        }

        class ObjectManipulator
        {
            private readonly IMyLogger _logger;

            public ObjectManipulator(IMyLogger logger)
            {
                _logger = logger;
            }

            public void Manipulate()
            {
                var anObject = new AnObject { State = "New" };
                _logger.LogObjectStateChenge(anObject);
            }
        }

        static void Main(string[] args)
        {
            var logger = new MyLogger();
            var manipulator = new ObjectManipulator(logger);
            manipulator.Manipulate();
        }
    }
}

You have a few options to get the class name: 您可以通过以下几种方法获取类名:

  1. Pass it as a parameter, ie LogObjectStateChange(AnObject anObject, Type type = null); 将其作为参数传递,即LogObjectStateChange(AnObject anObject, Type type = null);

  2. If you're targeting the 4.5 runtime you can use the CallerFilePath attribute to get the the file name, and extract the class name from that (assuming you have one file per class and the file name is the same as the class name), ie LogObjectStateChange(AnObject anObject, [CallerFilePath] string fileName = "") 如果您的目标是4.5运行时,则可以使用CallerFilePath属性获取文件名,然后从中提取类名(假设每个类有一个文件,并且文件名与类名相同),即LogObjectStateChange(AnObject anObject, [CallerFilePath] string fileName = "")

  3. Use reflection to get the calling class from the CallStack and StackFrame classes. 使用反射从CallStack和StackFrame类获取调用类。 Note though that in Release builds the compiler may inline methods or otherwise rearrange things, resulting in incorrect information in the stack trace. 请注意,尽管在Release版本中,编译器可能会内联方法或以其他方式重新安排内容,从而导致堆栈跟踪中的信息不正确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM