Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Logging Without Using Castle Windsor and the Logging Facility

As the discussion on the altdotnet list continued (some of it around my blog yesterday), it became apparent that some people didn't want to use an IoC container - but more confusing was that their objection to the whole pattern was that they thought the IoC container in here meant I was writing different code because I was using an IoC container. In fact nothing could be further from the truth - my service class would be identical in code, regardless of whether I used a container, or a factory, or any other construction on my object.

Let us look at the proposed service class again, a little expanded from the last example to show a bit more detail:

    public class MyService : IMyService

    {
        private ILogger logger;

        public ILogger Logger
        {
            get
            {
                if (logger == null) logger = NullLogger.Instance;
                return logger;
            }
            set { logger = value; }
        }


        public void DoMyThing()
        {
            // Do something here
            Logger.Debug("Hello");
        }
    }
    public interface IMyService
    {
        void DoMyThing();
    }

This service class is rather unimaginatively named, but has the basic parts in place. It has an optional ILogger property, and a method to DoMyThing(). One important thing to note is that the interface does not have an ILogger property.

So if we don't use an IoC container, we need some way to create instance of this class. The "old fashioned" way would use the new keyword, but this leads to all sorts of maintenance problems later on, and so we prefer to use some other kind of construction pattern, in this case a Factory, so here is our "application", albeit rather simple:

   class Program
    {
        static void Main(string[] args)
        {
            IMyService service = MyServiceFactory.Create();
            // Note that IMyService does not have a Logger property ...
            service.DoMyThing();
        }
    }

The thing to note here is that we only refer to the MyService class via the IMyService interface, so our consuming application does not know the service has a Logger property, nor does it care. In the Castle Windsor version earlier the line MyServiceFactory.Create() would have been something like IoC.Resolve<IMyService>() - but apart from that the consumer of the service has no idea how the object is being constructed, and nor does it care.

For the sake of this example, here is some dummy code to represent our Logging classes. In the Castle Windsor case we use the ILogger in the Castle assemblies, we could also use that in this example, but would probably want to write our own if we didn't want to use any of the Castle code.

    public class log4netLogger : ILogger
    {
        public void Debug(string message)
        {
            // Send to log4net here
        }
    }



    public interface ILogger
    {
        void Debug(string message);
    }

    public class NullLogger
    {
        public static ILogger Instance;
    }

Of course our ILogger will probably have a lot of other signatures defined, but this will do for now.

So now the only part of the equation missing is the actual factory we are going to use to replace the IoC container.

    public static class MyServiceFactory
    {
        public static IMyService Create()
        {
            MyService service = new MyService();
            service.Logger = LoggingServiceFactory.Create();
            // Do other initialisation here
            return service;
        }

    }

    public static class LoggingServiceFactory
    {
        public static ILogger Create()
        {
            return new log4netLogger();
        }
    }

That is all there is to it. It may seem like a lot of code to do a simple thing, and it is in a way - I would really try to avoid writing all this when Castle Windsor or an other IoC container will do all this for me - but it preserves one very important principle - the MyService class is totally clean, it does not have any knowledge of how it was constructed, and it does not know how it gets a logging class, it just knows that it can try and log something, and if it was meant to log, then it will.

This is the principle of Seperation of Concerns at work - the class has only one concern, and it isn't how to create a logger object.

 

 


Posted 06-20-2008 8:02 AM by Jak Charlton

[Advertisement]

Comments

Reflective Perspective - Chris Alcock » The Morning Brew #120 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #120
on 06-23-2008 3:21 AM

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #120

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)