Twitter RSS
Contact DevTrends

Blog Search

Latest Articles

Latest Comments

Popular Tags

Recent Months

Reading List

C# in Depth (2nd Edition)

Head First Design Patterns

Programming Entity Framework

Azure in Action

Dependency Injection in .NET

Suggest a Topic

If you think that you have a great idea for an article, please get in touch and let us know.

Technologies

This site was developed in C# using the following technologies: ASP.NET MVC 3 with the Razor view engine, SQL Server 2008 R2, Entity Framework 4.1 Code First, Castle Windsor, Automapper, jQuery and HTML5.

Jan17

Using Unity's automatic factories to lazy load expensive dependencies

Created on January 17, 2012 at 13:30 by Paul Hiles | Permalink | 2 comments

Automatic factory support in Microsoft's Unity IoC container is not something new, having been introduced with Unity 2.0 back in 2010. Unfortunately, not many people seem to know about it and the blog post that I used to find out about it is no longer available. This short post explains how to use automatic factories and why they can be useful.

Let's look at automatic factories in an example to help understand what they are and why they are useful. We will build a very small project that has a performance issue. We will then modify the code and use Unity's automatic factory support to remedy the problem. You can follow along theoretically, or practically by just copying the code into a console app, referencing Unity and adding some plumbing here and there.

To begin, we configure the IoC container exactly as you would normally do, registering your components at the root of your application:

		var container = new UnityContainer();
		container.RegisterType<ITestService, TestService>()
				 .RegisterType<IResource, ExpensiveResource>();
	

Here we have two registrations - a TestService and an ExpensiveResource. Let's assume that the TestService makes use of the ExpensiveResource resource, so it is injected via the constructor. All classes and interfaces are displayed below:

		public class TestService : ITestService
		{
			private readonly IResource _resource;

			public TestService(IResource resource)
			{
				_resource = resource;
			}

			public void DoSomething()
			{
				_resource.DoSomething();
			}

			public void DoSomethingElse()
			{
				// NB _resource is not used in this method
				// ...
			}
		}    

		public class ExpensiveResource : IResource
		{
			public ExpensiveResource()
			{
				Thread.Sleep(5000); //simulate expensive initialisation
			}

			public void DoSomething()
			{
				//do something
			}
		}

		public interface ITestService
		{
			void DoSomething();
			void DoSomethingElse();
		}

		public interface IResource
		{
			void DoSomething();
		}
	

The important things to note are:

1) ExpensiveResource is... well expensive. We have a Thread.Sleep call to slow it down and simulate a real world expensive resource such as an external web service call.

2) Note all methods on the TestService class actually use the ExpensiveResource.

If you added the necessary plumbing code to actually execute both TestService methods, you would find, as you would expect, that both calls are delayed by 5 seconds because of the ExpensiveResource initialisation. So we have a performance problem. The DoSomethingElse method is delayed even though it does not use the ExpensiveResource.

This is where Unity's automatic factory support can help. We can leave the Unity registration code exactly as it is, but we will make a few small changes to the TestService class:

		public class TestService : ITestService
		{
			private readonly Func<IResource> _resourceFactory;

			public TestService(Func<IResource> resourceFactory)
			{
				_resourceFactory = resourceFactory;
			}

			public void DoSomething()
			{
				_resourceFactory().DoSomething();
			}

			public void DoSomethingElse()
			{
				// _resource is not used in this method
			}
		}
	

As you can see, we have changed the class to take in a Func delegate that returns our resource rather than the resource itself. This means that when the TestService class is constructed, the ExpensiveResource class is not constructed at the same time. It is only instantiated when we call the delegate from within the DoSomething method.

If you were to run the code again, this time only the DoSomething method would be delayed. The DoSomethingElse method would return immediately because it does not use the ExpensiveResource and by using the factory (the delegate), the ExpensiveResource constructor is not called in this case. Problem solved! When you try and resolve the TestService, Unity will scan the constructor and see that a Func is required. Unity is smart enough to resolve this delegate, provided that IResource is registered with the container. The creation of the delegate is automatic - hence automatic factories.

Note that in the previous code, we invoked the delegate in the DoSomething method on every call. If you are going to be making multiple calls within the same lifetime of the service, it might make more sense to ensure that the delegate is only invoked once. Depending on your requirements, controlling it through a Unity lifetime might suffice or alternatively, you can do something like this:

		public class TestService : ITestService
		{
			private IResource _resource;
			private readonly Func<IResource> _resourceFactory;

			public TestService(Func<IResource> resourceFactory)
			{
				_resourceFactory = resourceFactory;
			}

			public void DoSomething()
			{
				Resource.DoSomething();
			}

			public void DoSomethingElse()
			{
				// _resource is not used in this method
			}

			private IResource Resource
			{
				get { return _resource ?? (_resource = _resourceFactory()); }
			}
		}
	

Now once the delegate has been invoked and the IResource implementation returned, we store it in a private member variable for future use, which is far more efficient that calling the delegate multiple times

Conclusion

Unity's automatic factory support allows you to lazy load expensive dependencies very easily. This is very useful in situations where an expensive dependency is not used in all code paths. With standard dependency injection of the resource, all methods and all code paths would experience the delays associated with instantiating the expensive resource. By injecting a factory instead, we can restrict this delay to code paths where the resource is actually used, potentially improving application performance significantly.


Sharing

If you found this article useful then we would be very grateful if you could help spread the word. Linking to it from your own sites and blogs is ideal. Alternatively, you can use one of the buttons below to submit to various social networking sites.

Twitter Facebook Digg Delicious Reddit StumbleUpon MySpace LinkedIn FriendFeed


Comments

Gravatar

Added on April 12, 2013 at 03:01 by Avi Jassra | Permalink

really nice post ...

Gravatar

Added on April 28, 2013 at 05:12 by Brett | Permalink

Agreed! Very nice post and exactly what I was looking for.

Thanks!


Add a comment

Fields marked with a are mandatory. No HTML please.

Used exclusively for Gravatar and never shared.

CAPTCHA