Unity Lifetime Manager

December 08, 2018

If you’ve ever used an IoC container, you’ll know that one of their benefits and burdens is that they abstract away from you the hassle of managing your dependencies. Just declare your interfaces as constructor parameters and then register those dependencies at startup, and the IoC container will propogate your class. Your registration may look like this:



    container.RegisterType<IMyService, MyService>();

But what about when your class has state? For example, what if I have this sort of thing:



    container.RegisterType<IMyData, MyData>();

Here we’re using unity, but it appears that the default behaviour for most IoC containers is transient - that is, they are created each time they are resolved. This is important, not just because you will lose data that you thought you had (in fact that’s one of the better scenarios - because it’s obvious that it’s not behaving how you expect), but because if you’re caching results of queries and so forth, you might find your application is going back for data that you thought it already had. Here’s an example, using Unity, that proves this:



static void Main(string[] args)
{
    var container = new UnityContainer();
 
    container.RegisterType<IMyService, MyService>();
    container.RegisterType<IMyData, MyData>();
 
    container.Resolve<IMyData>().Test = "testing";
    container.Resolve<IMyService>().TestFunction();
 
    Console.ReadLine();
}

The service class might look like this:




public interface IMyService
{
    void TestFunction();
}
 
public class MyService : IMyService
{
    private readonly IMyData myData;
 
    public MyService(IMyData myData)
    {
        this.myData = myData;
    }
 
    public void TestFunction()
    {
        Console.WriteLine($"Test Data: {myData.Test}");
    }
}

And the data class:



public interface IMyData
{
    string Test { get; set; }
}
public class MyData : IMyData
{
    public string Test { get; set; }
}

If you run that, you’ll see that the output is:



Test Data: 

Different IoC containers have slightly different life times - in fact, in the .Net Core IoC, you have to now explicitly register as Singleton, Transient or Scoped. In Unity, you can do something like this:



static void Main(string[] args)
{
    var container = new UnityContainer();
 
    container.RegisterType<IMyService, MyService>(new ContainerControlledLifetimeManager());
    container.RegisterType<IMyData, MyData>(new ContainerControlledLifetimeManager());
 
    container.Resolve<IMyData>().Test = "testing";
    container.Resolve<IMyService>().TestFunction();
 
    Console.ReadLine();
}



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024