Sunday, July 29, 2012

Lazy Unity Injection

Adapting a legacy project to use proper Dependency Injection can be difficult.

Often times your services can not be singletons, and then those dependencies cause chains of other services to require transient lifetimes. Sometimes these service dependency trees can grow deep, and their initialization can become quite expensive. If you are working with a website, those big trees can add up and cost a lot of time and memory with every request.

One way to trim a deep or expensive dependency tree is to inject Lazy types of your services.

Lazy injection will prevent an optional resource from being instantiated until it is actually needed. While this is not a scenario that you want to architect your application into voluntarily, it can be a crucial performance optimization. Have you ever taken a memory dump of your website and found thousands of services floating in memory? I have, and let me assure you, it's not pretty!

LazyExtension for Unity

public class LazyExtension : UnityContainerExtension
    protected override void Initialize()
            new LazyBuildPlanPolicy(), 
    public class LazyBuildPlanPolicy : IBuildPlanPolicy
        public void BuildUp(IBuilderContext context)
            if (context.Existing != null)
            var container = context.NewBuildUp<IUnityContainer>();
            var typeToBuild = context.BuildKey.Type.GetGenericArguments()[0];
            var nameToBuild = context.BuildKey.Name;
            var lazyType = typeof(Lazy<>).MakeGenericType(typeToBuild);
            var func = GetType()
                .Invoke(this, new object[] { container, nameToBuild });
            context.Existing = Activator.CreateInstance(lazyType, func);
        public Func<T> CreateResolver<T>(
            IUnityContainer currentContainer, 
            string nameToBuild)
            return () => currentContainer.Resolve<T>(nameToBuild);

Unit Tests

public interface ITestClass
    int HighFive();
public class TestClass : ITestClass
    public static int InstanceCount = 0;
    public TestClass()
        Interlocked.Increment(ref InstanceCount);
    public int HighFive()
        return 5;
public class TestFixture
    public void Test()
        using (var container = new UnityContainer())
            container.RegisterType<ITestClass, TestClass>();
            var testClass1 = container.Resolve<Lazy<ITestClass>>();
            Assert.AreEqual(false, testClass1.IsValueCreated);
            Assert.AreEqual(0, TestClass.InstanceCount);
            Assert.AreEqual(5, testClass1.Value.HighFive());
            Assert.AreEqual(true, testClass1.IsValueCreated);
            Assert.AreEqual(1, TestClass.InstanceCount);
            var testClass2 = container.Resolve<Lazy<ITestClass>>();
            Assert.AreEqual(false, testClass2.IsValueCreated);
            Assert.AreEqual(1, TestClass.InstanceCount);
            Assert.AreEqual(5, testClass2.Value.HighFive());
            Assert.AreEqual(true, testClass2.IsValueCreated);
            Assert.AreEqual(2, TestClass.InstanceCount);
kick it on


1 comment:

  1. Good to see you again, write my research paper for me cheap ! Your order will be additionally checked by a competent proofreader for plagiarism. We use the latest technology advancements (CopyScape, TurnItIn, etc.) to ensure 100% originality of produced content. You are guaranteed to receive a plagiarism-free paper written from scratch and in compliance with your requirements.


Real Time Web Analytics