Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Unity Application Block and Decorator Pattern

Unity Application Block and Decorator Pattern


by David Hayden


 


Recently I discussed the Decorator Pattern as well as Array Injection using Unity and I thought I would put concepts from both of these together to clean up the code I had written earlier with regards to filtering messages being logged to a ConsoleLogger.


 


Simplify Responsibilities


One could argue that the ConsoleLogger created in the previous post has too many responsibilities. It is both in charge of filtering messages as well as logging to the console, which can be a violation of the Single-Reponsibility Principle ( SRP ). We also can’t re-use the filtering logic with a DatabaseLogger, for example, without duplicating the filtering logic from logger to logger. This could lead us into violation of the DRY Principle.


 


 


public class ConsoleLogger : ILogger


{


    private readonly ILogFilter[] _filters;


 


    public ConsoleLogger(ILogFilter[] filters)


    {


        _filters = filters;


    }


 


    public void Log(LogMessage message)


    {


        foreach(var filter in _filters)


            if (!filter.CanLog(message))


                return;


 


        Console.WriteLine(message.Message);


    }


}


 


 


A better approach would be to split the filtering and logging logic between 2 classes, perhaps a FilteringLoggerDecorator and a ConsoleLogger. Let’s get the ConsoleLogger back to simple logging:


 



public class ConsoleLogger : ILogger


{


    public void Log(LogMessage message)


    {


        Console.WriteLine(message.Message);


    }


}


 


and then put the filtering in the FilteringLoggerDecorator:


 



public class FilteringLoggerDecorator : ILogger


{


    private readonly ILogFilter[] _filters;


    private readonly ILogger _inner;


 


    public FilteringLoggerDecorator(ILogFilter[] filters, ILogger inner)


    {


        _filters = filters;


        _inner = inner;


    }


 


    public void Log(LogMessage message)


    {


        foreach (var filter in _filters)


            if (!filter.CanLog(message))


                return;


 


        _inner.Log(message);


    }


}


 


Now with the responsibilities better separated, let’s add the new classes to the UnityContainer for use in an application.


 


Setting Up the UnityContainer


 


Like before, the filters will be registered with the UnityContainer as follows:


 



IUnityContainer container = new UnityContainer();


 


container.RegisterInstance<ILogFilter>(“CategoryFilter”, new CategoryFilter(new[] { “Security” }));


container.RegisterInstance<ILogFilter>(“PriorityFilter”, new PriorityFilter(3, 5));


 


The ConsoleLogger is then registered as an ILogger named instance ( not the default ). For brevity I didn’t specify a particular LifetimeManager as before.


 



container.RegisterType<ILogger, ConsoleLogger>(“Console Logger”);


 


The FilteringLoggerDecorator is registered as the default ILogger Instance. I specify in the registration that the ConsoleLogger is to be injected into the FilteringLoggerDecorator’s constructor along with the array of filters ( again not specifying a LifetimeManager ):


 



container.RegisterType<ILogger, FilteringLoggerDecorator>(new InjectionConstructor(typeof (ILogFilter[]),


                                                                                new ResolvedParameter(


                                                                                    typeof (ILogger),


                                                                                    “Console Logger”)));


 


Now you can resolve the ILogger from the UnityContainer and experience the same results as in the previous tutorial. Only now the filtering and logging can change independently of one another allowing easier development and maintainenance.


 



var logger = container.Resolve<ILogger>();


 


logger.Log(new LogMessage { Category = “Security”, Priority = 3, Message = “This is a test.” });


 


Conclusion


Next time let’s remove the FilteringLoggingDecorator and replace it with a custom ICallHandler. We can then use the Interception Extension in Unity along with the new InterfaceInterceptor to achieve the filtering using AOP as an alternative to the Decorator Pattern. For more information, you can check out other Unity Tutorials.


 


Hope this helps,


David Hayden


 


Recent Posts:



 

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>