Alois Kraus

February 2006 Entries

Programatic Configuraton - Enterprise Library (v2.0) Logging Block

The following code sample shows how to configure the Enterprise Library Logging Block programatically without the help of ObjectBuilder. To create a working LogWriter instance with your own settings you need to create the following objects:
  • A Formatter which contains a valid message template
  • A LogSource which has a name (Category) contains a colleciton of Listeners (Sinks) along with the Formatter.
  • A collection LogSources with the category as key and the LogSource object as value
To use this logger you can call

  ConfigLessLogger.Error("Hello world of config by code.");
The error is written to the Windows Event Application Event Log:

Timestamp: 16.02.2006 23:33:41
Message: Hello World of dynamic object creation
Category: Errors

I have improved my original ConfigLessLogger sample with the very helpful comments from David Hayden who blogs about the Enterprise Library (mainly IConfigurationSource and Logging Block).

ConfigLessLoger.cs

using System;

using System.Collections.Generic;

using Microsoft.Practices.EnterpriseLibrary.Logging;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;

using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;

using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

 

namespace MyApp.Logging

{

    public class ConfigLessLogger

    {

        private static LogWriter writer;              // Instance is created in static ctor which is thread safe

        const string EventLogSource = "Code Source"// Event Log Source name

        const string ErrorCategory = "Errors";        // We have only one message category: Errors

 

        static ConfigLessLogger()

        {

            writer = CreateLogWriterFromCode();  // static ctor is thread safe according to ECMA standard section 9.5.3

        }

 

        static private LogWriter CreateLogWriterFromCode()

        {

            // This is our message template for any Sink you add below in our case the Windows Event Log

            TextFormatter formatter = new TextFormatter("Timestamp: {timestamp}{newline}" +

                                                        "Message: {message}{newline}"    +

                                                        "Category: {category}{newline}"    );

 

            LogSource emptyTraceSource = new LogSource("none");

 

            LogSource errorsTraceSource = new LogSource(ErrorCategory, System.Diagnostics.SourceLevels.All);

            // Create for all Errors a Listener which writes the messages to the Windows Event Log

            // with the Event Log Source Property "Code Source". The message format is specified by

            // the TextFormatter which is in our case the template above.

            errorsTraceSource.Listeners.Add(new FormattedEventLogTraceListener(EventLogSource, formatter));

 

            IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();

            // Add to Category "Error" our EventLog Listener with the corresponding category in it.

            traceSources.Add(errorsTraceSource.Name, errorsTraceSource);

 

            return new LogWriter(new ILogFilter[0], // ICollection<ILogFilter> filters

                              traceSources,        // IDictionary<string, LogSource> traceSources

                              emptyTraceSource,    // LogSource allEventsTraceSource

                              emptyTraceSource,    // LogSource notProcessedTraceSource

                              errorsTraceSource,    // LogSource errorsTraceSource

                              ErrorCategory,        // string defaultCategory

                              false,                // bool tracingEnabled

                              true);                // bool logWarningsWhenNoCategoriesMatch

        }

 

        /// <summary>

        /// Write an Error message to the Windows Event Log with an message template specifed in code

        /// </summary>

        /// <param name="message">Error message to log</param>

        public static void Error(string message)

        {

            LogEntry ent = new LogEntry();

            ent.Categories.Add(ErrorCategory);  // To use another category use traceSources.Add("OtherCat", Listener);

            ent.Message = message;

            ent.Severity = System.Diagnostics.TraceEventType.Error;

            writer.Write(ent);

        }

    }

}


Call Properties through delegates and pass them by Reference

 After reading Mike Stalls Debugging Blog I was wondering if it is really impossible to pass property values by reference:
    void PassIntByRef(ref int x)
    ...
    PassIntByRef(ref MyProperty);
  <-- this is illegal in C#.
Another restriction which is often annoying is that you cannot have property delegates.

    class PropertyDelegation

    {

        public delegate int ReturnValueDelegate();

 

        ReturnValueDelegate ValueGetter;

 

        int x = 0;

        public int X  // This is our beloved property we care so much about.

        {

            get { return x; }

            set { x = value; }

        }

 

        public PropertyDelegation()

        {

            ValueGetter = X;      // Illegal in C#

            ValueGetter = GetX;   // Legal code

        }

        int GetX()

        {

            return X;

        }

   }


The above workaround with the GetX function is not really nice but it works and I wondered if there is no other way to do this. After 10 minutes thinking about this I did realize that both problems could be solved by a reference type which provides the needed functionality.
  • The new type should provide a getter and setter for the wrapped property.
  • Expose Get and Set functions to attach delegates to it
  • Provide a as much type safety as possible.
Lets look what the C# compiler does produce for a Property with a getter and setter. Using Reflector we quickly see what really happens:
Property with Getter and Setter under the Reflector Microscope
Hm the property is in reality a set of two methods. If we get our hands on both methods we can create a delegate from it and call them by our selfs inside our wrapper class (reference type object). Extensions to compiled types at run time calls for the reflection API. In our case the PropertyInfo class provides all information we want. The result of this is my new class PropertyInvoker which fulfills all three requirements.

    public class PropertyInvoker

    {

        private PropertyInfo propInfo;

        private object obj;

 

        public PropertyInvoker(string PropertyName, object o)

        {

            obj = o;

            propInfo = o.GetType().GetProperty(PropertyName);

        }

 

        public T Property

        {

            get

            {

                return (T) propInfo.GetValue(obj, null);

            }

 

            set

            {

                propInfo.SetValue(obj, value, null);

            }

        }

 

        public T GetProperty()

        {

            return Property;

        }

 

        public void SetProperty(T value)

        {

            Property = value;

        }

    }


This little helper allows us to create a delegate function from a property:

        public delegate int ReturnValueDelegate();

        ReturnValueDelegate ValueGetter;


        // Create delegate around the get property of X

        ValueGetter = new ReturnValueDelegate(new PropertyInvoker<int>("X", this).GetProperty);

        int realval = ValueGetter.Invoke(); // Call get property with our new invoker


Properties cannot be really passed by reference but at least we did come quite close to our initial goal:

        private void Add(PropertyInvoker<int> value)

        {

            value.Property++;

        }


        // Pass property by reference inside wrapped type

        Add(new PropertyInvoker<int>("X", this));

 

Ok this looks nice but how about performance? Reflection is known to be slow after all. The good news is that on my P4 3.0 GHz PC at home I can call value.Property++ over 300 000 times/s. This is quite good for an indirect function call via reflection. The bad news is the native property is much better. To be precise about several hundred times faster. Why? I think the JITer is very good at detecting this set_X and get_X methods in my code and does simply inline the calls. Against inlined function calls my PropertyInvoker has clearly no chance since at runtime there is no method call due to god work of the JITer. To check this assumption and to prevent such an unfair "optimization"I decorated the getter and setter of my property with the [MethodImpl(MethodImplOptions.NoInlining)] attribute to prevent inlining. After that I got "only" a performance penalty of about 200 times slower than the native method call. To sum it up: My method is much slower as a native property (or wrapped function call) but still far away from being slow in absolute terms. If  this little class does help you to write nicer and cleaner code give it a try.

Patterns and Practices Champions Award

Good news. I am a Patterns and Practices Champions Award winner. I am very happy to be given this award by the Microsoft Patterns and Practices team. There is much more to be told about best programming practices for the .NET platform and especially the Enterprise Library. At the moment I have very little time since I have some new challenges at work to master and the urgent need to go skiing in the Alps in Austria ;-). But I promise to do my best to post some a small sample on how to use the Enterprise Library Dependency Injection mechanism to build a simple plugin interface where each plugin configures itself. By the way if somebody nows how to deal with a StackOverFlowException in .NET 2.0 let me know. The documented mechanism via RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup does not work for me. The process is always terminated by the Runtime without executing ever any cleanup code.