Logging NLog Messages to a Non-static Method

I’ve used the NLog logging library for .NET for a few projects in the past, and have absolutely loved it. It is extremely easy to configure and extremely flexible.

One thing that I just ran into was that the built-in MethodCallTarget can only send log messages to a static method. In my particular case, I wanted to grab all of the log messages that were occurring in the entire AppDomain, and funnel them into an instance (non-static) method of a class. Thankfully NLog is also very easy to extend, so I just wrote my own log target. More specifically, I just subclassed the MethodCallTargetBase and overrode the DoInvoke method:

    public class InstanceMethodCallTarget : MethodCallTargetBase
    {
        private MethodInfo m_MethodInfo;

        public InstanceMethodCallTarget()
            : base()
        {
        }

        #region Property - ClassInstance
        private object m_ClassInstance;
        public object ClassInstance
        {
            get
            {
                return m_ClassInstance;
            }
            set
            {
                m_ClassInstance = value;
                UpdateMethodInfo();
            }
        }
        #endregion

        #region Property - MethodName
        private string m_MethodName;
        public string MethodName
        {
            get
            {
                return m_MethodName;
            }
            set
            {
                m_MethodName = value;
                UpdateMethodInfo();
            }
        }
        #endregion

        private void UpdateMethodInfo()
        {
            if ((this.ClassInstance != null) && (this.MethodName != null))
            {
                m_MethodInfo = this.ClassInstance.GetType().GetMethod(this.MethodName);
            }
            else
            {
                m_MethodInfo = null;
            }
        }

        protected override void DoInvoke(object[] parameters)
        {
            if (m_MethodInfo != null)
            {
                m_MethodInfo.Invoke(this.ClassInstance, parameters);
            }
        }
    }

I can understand why such a target doesn’t come with NLog — the ClassInstance property cannot be instantiated from the XML config file and must be programmatically specified.
For example:

            LoggingConfiguration config = LogManager.Configuration;
            if (config == null)
            {
                config = new LoggingConfiguration();
            }

            InstanceMethodCallTarget target = new InstanceMethodCallTarget();
            target.ClassInstance = this;
            target.MethodName = "LogMessage";
            target.Parameters.Add(new MethodCallParameter("${level}"));
            target.Parameters.Add(new MethodCallParameter("${message}"));

            config.AddTarget("TargetNameHere", target);
            config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, target));

            LogManager.Configuration = config;

Since two MethodCallParameters were added to the Parameters collection, the method that NLog invokes behind-the-scenes must take two string parameters and return void. For example:

        public void LogMessage(string level, string message)
        {
            // Do something here, like fire an event with the log level and log message
        }

NLog is a great library with a very well thought-out and flexible API.


You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

AddThis Social Bookmark Button

Leave a Reply