Search code examples
c#loggingdependency-injectionenterprise-library

entlib CustomTraceListener unresolved


im new to Enterprise Library (5, with the optional update), and am trying to use my own CustomTraceListener with the Logging Block.

Logging works with a supplied flat file listener, but i dont seem to be able to extend that to my custom class.

Logs to FlatFileListener, but Not to my CustomListener:

    static UnityContainer _container;
    static LogWriter _writer;

    internal static void Inf(this string message)
    {
        if (_container == null)
        {
            _container = new UnityContainer();
            _container.AddNewExtension<EnterpriseLibraryCoreExtension>();
        }
        if (_writer == null && _container != null)
        {
            _writer = _container.Resolve<LogWriter>();
            LogEntry log = new LogEntry();
            log.Message = message;
            log.Categories.Add("Information");
            log.Severity = TraceEventType.Information;
            _writer.Write(log);
        }
    }

My CustomListener based on bychkov:

namespace Test.Catch
{
    [ConfigurationElementType(typeof(CustomTraceListenerData))]
    public class LoggerCustom : CustomTraceListener
    {
        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
        {
            if (data is LogEntry && this.Formatter != null)
            {
                this.WriteLine(this.Formatter.Format(data as LogEntry));
            } else
            {
                this.WriteLine(data.ToString());
            }
        }

        public override void Write(string message)
        {
            Trace.Write(message);
        }

        public override void WriteLine(string message)
        {
            Trace.WriteLine(message);
        }
    }
}

First i tried to add the customtracelistener with the Configuration Editor, but the configuration editor did not list/detect any customtracelisteners, which i suspect is part, or whole of the problem?

So instead, i added the following, again, based on bychkov:

app.config listener manual addition

  <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
  type="Test.Catch.LoggerCustom, Test.Catch" traceOutputOptions="None"
  name="Custom Trace Listener" initializeData="" formatter="Text Formatter Plain" />

Now when I call Inf("logme"), with the above app.config addition included, then an exception is thrown at _container.AddNewExtension(): The type 'Test.Catch.LoggerCustom, Test.Catch' cannot be resolved.

Given I dont understand the underlying mechanisms, how could i get to logging with my custom listener?

  1. Do i need to create my own TraceListenerData, like the Tavares solution ?

  2. Or do i need to understand and mess with UnityDefaultBehaviorExtension, as detailed by MacLeod ?

  3. Is the existing code wrong?

  4. Or the solution lies elsewhere?

Thank you for your expertise.


Solution

  • Go grab the Entlib 5 extensibility labs. There's an entire chapter on writing custom trace listeners. You'll learn the underlying technologies, why things work the way they do, how it fits together, and then you'll be able to answer your own questions.

    As for why the above doesn't work: when using CustomXXXData configuration classes, your provider needs a constructor that takes a NameValueCollection. You don't have one, so your code is in fact wrong. Work through the labs, you'll learn that and more.