RoBlog – Refactoring Reality

Discrete thought packets on .Net, software development and the universe; transmitted by Rob Levine

Using log4net with Unity (part 2) – UnityLog4NetExtension now on NuGet

by Rob Levine on 21-Dec-2013

Following on from a previous post, the solution detailed has now been renamed to “UnityLog4NetExtension” and is now available as a NuGet package as well as via GitHub.

So if you want to dependency inject the correct log4net ILog logger instance for your type, all you need to do is:

1) reference the NuGet package
2) add the extension to your unity IContainer instance with

1
container.AddNewExtension<Log4NetExtension>();

3) and add your ILog dependencies wherever you need a log4net logger:

1
2
3
4
5
6
7
8
9
public class MyClass
{
    private readonly ILog _logger;
 
    public MyClass(ILog loggerForMyClass)
    {
        _logger = loggerForMyClass;
    }
}

Enjoy!

Unity does not respect HierarchicalLifetimeManager when manually registering UnityServiceLocator with the container

by Rob Levine on 15-Mar-2013

I’ve been trying to phase out some usage of the static ServiceLocator pattern in our codebase. There are many reasons not to like this, which I won’t go into here:

1
var foo = ServiceLocator.Current.GetInstance();

In order to try and make the changes in small incremental steps, my first plan was to allow the IServiceLocator instance to be injected into classes as a dependency at construction time by Unity. This would allow me to make minimal changes; first I’d register an instance of UnityServiceLocator with the DI container, and then make a few small changes to the classes, just switching calls like the above to something like:

1
var foo = serviceLocator.GetInstance();

This gets rid of the rather horrible “static-ness” of the service locator pattern.

Once verified as working, I’d then proceed to inject the actual dependencies themselves, rather than the service locator.

However, I seem to have stumbled across some rather horrible Unity behaviour. What I’m seeing suggests that Unity treats the UnityServiceLocator (the Unity implementation of IServiceLocator) as a static singleton, even when it is configured otherwise, and this behaviour seems to be particular to UnityServiceLocator.

In the following code, I register an injection factory to create a new instance of UnityServiceLocator. I also scope it with HierarchicalLifetimeManager to give me one instance per child container:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static void Main(string[] args)
{
    var container = new UnityContainer();
    container.RegisterType(
        new HierarchicalLifetimeManager(),
        new InjectionFactory(
            c =&gt;
                {
                    Console.WriteLine("InjectionFactory invoked with container: " + c.GetHashCode());
                    return new UnityServiceLocator(c);
                }));
 
    container.Resolve(); // expect to see console output here
    container.Resolve(); // don't expect to see console output here
 
    var child = container.CreateChildContainer();
    child.Resolve(); // expect to see console output here
    container.Resolve(); // don't expect to see console output here
 
    var anotherChildContainer = container.CreateChildContainer();
    anotherChildContainer.Resolve(); // expect to see console output here
    anotherChildContainer.Resolve(); // don't expect to see console output here
}

I would expect the above code to invoke the factory, create the UnityServiceLocator instance and write out console output three times, once for each container. It doesn’t – it does it once, as if I’d registered it as a singleton:

InjectionFactory invoked with container: 20903718

It gets worse:

If I now make my own class implement IServiceLocator (literally, implement the interface, add one constructor which takes IUnityContainer, and have all methods throw NotImplementedException), and swap the line

1
return new UnityServiceLocator(c);

with

1
return new MyUnityServiceLocator(c);

This starts behaving the way I’d expect:

InjectionFactory invoked with container: 20903718 
InjectionFactory invoked with container: 51746094 
InjectionFactory invoked with container: 41215084

I just cannot understand this behaviour unless Unity treats UnityServiceLocator as a special case and always makes it a singleton.

This feels like a bug to me, or possibly some undocumented special behaviour. Either way, it is nasty, and cost me a fair bit of time.

ADDENDUM:

Thanks to user Randy Levy (Enterprise Library Support Engineer) on Codeplex for explaining the reason for this behaviour. The UnityServiceLocator itself registers itself with an ExternallyControlledLifetimeManager lifetime:

public UnityServiceLocator(IUnityContainer container)
{
    this.container = container;
    container.RegisterInstance<IServiceLocator>(this, new ExternallyControlledLifetimeManager());
}

The full discussion can be found here.

 

 

Using log4net with Unity

by Rob Levine on 28-Dec-2012

[EDIT: the Unity extension described here is now available as a NuGet package. See this post for more information]

When using log4net, it is quite common to create loggers for each class using something like:

1
2
3
4
public class MyClass
{
   private static readonly ILog logger = LogManager.GetLogger(typeof(MyClass));
}

I’ve been following this pattern for years, but more recently it has begun to bother me. I tend to use Unity and constructor injection for most dependency injection requirements I have, but the above logger pattern doesn’t fit nicely into this dependency injection approach. I would really like to be able to write the following code and receive a similarly configured logger:

1
2
3
4
5
6
7
8
9
public class MyClass
{
    private readonly ILog logger;
 
    public MyClass(ILog logger)
    {
        this.logger = logger;
    }
}

There has been some discussion online as to how best to acheive this:

http://stackoverflow.com/questions/6846342/how-to-inject-log4net-ilog-implementations-using-unity-2-0
http://davidkeaveny.blogspot.co.uk/2011/03/unity-and-log4net.html
http://blog.baltrinic.com/software-development/dotnet/log4net-integration-with-unity-ioc-container

In the last of these links, Kenneth Baltrinic describes a solution. However, although his solution works, it involves some stack walking to identify the Type of the logger to create. I felt that this should be available from within Unity itself without the need to resort to handling StackTrace/StackFrame classes, and so I set about writing a solution to the problem in a similar vein to Kenneth’s, but using the hooks within Unity to track the object creation stack and to be able to work out “for whom am I creating this ILog instance”?

I ended up writing three extensions, all of which can be found here:

https://github.com/roblevine/UnityLog4NetExtension

They are:

CreationStackTrackerExtension

This extension is responsible for maintaining a stack of the type creation heirarchy. At the creation of any given type via unity, the stack provided by this extension will show the parent class, grandparent, etc. This extension is used by both the extensions listed below.

Log4NetExtension

Relying on the extension above, this intercepts any request for an ILog instance and creates an ILog instance by calling LogManager.GetLogger(Type t) using the type of the parent class (ie the class the logger is being injected into)

CreationStackReporterExtension

Relying on the CreationStackTrackerExtension extension above, this extension will resolve any dependency of type UnityObjectCreationStack, and inject an instance that has a copy of the object creation stack, as maintained by CreationStackTrackerExtension.

So now, by simply registering the appropriate extension:

1
2
   var container = new UnityContainer();
   container.AddNewExtension();

I can have the correct ILog implementation injected into my class.

ConfigGen – .NET Configuration File Generator

by Rob Levine on 30-Jun-2010

After a week and a half off work and on holiday, which consisted of me working solidly on my new pet project, I am pleased to announce the first (alpha) release of ConfigGen – .NET Configuration File Generator.

ConfigGen is a .Net configuration file generation tool, and it is intended to make the .Net developer’s life easier. Much easier, if my experience of how some dev teams go about managing their configuration files is anything to go by! I’ve written various forms of this tool at several different places, all to tackle the same basic problem of having to manage loads of different configuration files for different machines and environments. This version on CodePlex is completely new, started from scratch, with no code borrowed or copied. Hopefully it is all the better for it!

It is a pretty simple tool; no rocket science was necessary. Basically, you maintain an xml template and a settings spreadsheet. The template looks pretty much like your existing configuration file, except that values that are different between machines/environments are tokenised. The settings spreadsheet has a list of all the tokens across the top, and all the machines/environments requiring their own config down the left hand side. Predictably enough, ConfigGen generates one configuration file for each row in the spreadsheet, replacing the tokens with their spreadsheet values as it goes. Additionally, it allows the structure of the configuration file to be changed, depending on the value of these settings in the spreadsheet.

This release is an early alpha version, but have a look and let me know what you think. So please, head over to the project’s CodePlex page and hopefully save yourself the frustration of discovering your config files are out of sync on your next push to your production environment!

Check it out at:

http://configgen.codeplex.com/

Refix – .NET dependency management tool

by Rob Levine on 14-Jun-2010

Just a short blog entry to highlight an exceptionally cool project that a colleague of mine has been working on in his spare time: Refix. A .NET dependency management tool.

This tool attacks the problem of having a project with dependencies, where these dependencies themselves may have common, but different version, assemblies.

I’ve certainly had this problem many times: you have a solution that uses other third party assemblies all of which have common dependencies (such as log4net, perhaps), but different assemblies rely on different versions of this common item.

Refix helps you tackle this problem in two ways:

Firstly, it goes through your solution to work out if there is actually a common set of dependencies that can be used. If so it can re-write your project files accordingly.

If there isn’t, you can supply it with a list of compatible versions (e.g. tell it v 1.1.1.0 is compatible with v 1.1.2.0), and it can automatically insert the correct assembly redirects for you into the applicaiton configuration files.

It is looking to be an excellent tool so far. It is in the early stages, but completely useable and it tackles a problem that I’ve not seen solved in .Net before.

Check it out:

http://refix.codeplex.com/