Configuring Log4net in code using Windsor Installers

 

Castle provides a great way to structure the setup of your application using the installers. Ninject providers a similar mechanism with modules which you could also use.

Managing configuration was getting pretty painful on my current project, so cutting it down was necessary. Since we don’t need to edit most of the log4net configuration after a build is done, compiling this in is acceptable.

We are using the log4net facility for castle, so this is the first thing we set up.

public class LoggingInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        if (!container.Kernel.GetFacilities().OfType<LoggingFacility>().Any())
        {
            container.AddFacility("logging", new LoggingFacility(LoggerImplementation.Log4net));
        }

        var root = ((Hierarchy)LogManager.GetRepository()).Root;
        root.AddAppender(GetEventLogAppender());
        root.Repository.Configured = true;
    }
}

 

Next we set up an EventLog appender using the built in object model provided by log4net.

private static IAppender GetEventLogAppender()
{
    var patternLayout = new PatternLayout("%appdomain [%thread] %-5level - %message%newline [%properties]%newline %exception");

    var eventLogAppender = new EventLogAppender
                               {
                                   Name = "Application",
                                   Layout = patternLayout,
                                   ApplicationName = "MyApp",
                                   SecurityContext = NullSecurityContext.Instance
                               };
    return eventLogAppender;
}

 

And after calling container.Install(new LoggingInstaller()) we have logging without writing a single line of XML!

WCF, RouteTables and Castle Windsor

 

We are using the routing functionality to give our RESTful WCF service nice endpoints, however I ran into trouble, none of our services were being injected.

The service had two constructors which seemed odd, an empty one and one with dependencies specified…

public Api()
{
}

public Api(IBasket basketService)
{
    _basketService = basketService;
}

The injected services were NULL, so I removed the public constructor and got:

image

This sounds like the default WCF factory at work, checking the SVC files we get:

<%@ ServiceHost 
    Language="C#" 
    Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" 
    Service="MyProject.Api" 
%>   

That’s also configured correctly, but we have overridden the default routing, let’s take a look at that:

RouteTable.Routes.Add(new ServiceRoute("Api", new ServiceHostFactory(), typeof(Api)));

That looks like the default WCF factory to me… Doh! Let’s fix that up…

RouteTable.Routes.Add(new ServiceRoute("Api", new DefaultServiceHostFactory(container.Kernel), typeof(IApi)));

Great, we are now using the windsor factory, and we can remove the default parameter-less constructor from our API service.

Older Posts