简体   繁体   中英

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).

In my app I am using a logging class implementing a logging interface (following 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. 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).

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);

  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 = "")

  3. Use reflection to get the calling class from the CallStack and StackFrame classes. Note though that in Release builds the compiler may inline methods or otherwise rearrange things, resulting in incorrect information in the stack trace.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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