Disposing Instances when Using Inversion of Control
In the last few posts I have written about how to deal with IDisposable instances when using Dependency Injection. In the Who Disposes Your Repository I talk about the possibilities and challenges of disposing a repository which is injected. Then in the Extending Unity Container for IDisposable Instances (part 1
In the last few posts I have written about how to deal with IDisposable
instances when using Dependency Injection. In the Who Disposes Your Repository I talk about the possibilities and challenges of disposing a repository which is injected. Then in the Extending Unity Container for IDisposable Instances (part 1 and part 2) I show how automatic dispose of all IDisposable
instances can be achieved with Unity Container. This post completes the solution by detailing when the Container Hierarchies (aka Scoped Containers) are built and how they work with a Service Locator.
What we want to achieve is that all the IDisposable
instances are disposed when no longer needed. Making this more specific, we want that all the IDisposable
instances created within one defined scope to be disposed when that scope ends. In C# we have language support for this. We can use the using statement like this:
using (IDisposable o = new DisposableClass())
{ // scope begins
// do stuff with o within this scope
} // scope ends
Inside the brackets of this using statement we can use the IDisposable
instance as we want and we are assured that it will get disposed when the scope ends.
We can use the using statement only if:
- the begin and the end of the scope is in the control of our code (we write the code that defines the scope)
- the creation of the IDisposable instance is in the control of our code (we write the code that calls its constructor)
By doing Inversion of Control we give the control of the above to the frameworks we are using.
When we are using Dependency Injection, we no longer call the constructors. A framework (Unity Container maybe) will call it for us. However, we can still dispose instances, if we put the container itself in the using statement:
using (var scopeContainer = mainContainer.CreateChild())
{ // scope begins
// do stuff with o within this scope
// all the instance created within this scope are created by the scopeContainer
} // scope ends
Mainly we create one container for each scope and we dispose it when the scope ends. When the scoped container gets disposed, it will dispose all the IDisposable
instances that it created (previous posts show how this can be done with Unity Container). This is how the idea of using Container Hierarchies for disposing instances came into place. Therefore, if we leave to the framework the control of building instances, we also expect the framework to dispose the instances it created. We still need to make sure that when the scope begins a new container is associated with it, and within that scope all the instances are built with the associated container.
When we are in a web application, we are not in the control of defining the scope neither (Inversion of Control again). We might want to consider this scope to be the same with handling a web request or with a web session. For example, we would want to nest all the code that handles a request within a using statement as we did above. Something quite similar would be: when the request begins create the scoped container, then keep it on the request so all the code running on that request could use it to get new instances, and when the request ends dispose it. Again, if the framework is in control of defining the scope we are interesting in, the framework should give us some hooks which we can use to run some code when the scope begins or ends and to give us some object that represents a context for this scope, so we can keep a reference to the scoped container on it.
Most of the web frameworks give such hooks. We are signaled when a request or session begins or ends. There is also an object which is easy to access, which represents the current request or session and on which we can store context information. If we are using ASP.NET MVC, which is designed with Dependency Injection in mind, we can get this done quite easy. Below is a code snippet from DevTrends github repository, which contains small projects that integrate Unity Container with ASP.NET MVC and ASP.NET Web API.
public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (typeof(IController).IsAssignableFrom(serviceType))
{
return ChildContainer.Resolve(serviceType);
}
return IsRegistered(serviceType) ? ChildContainer.Resolve(serviceType) : null;
}
protected IUnityContainer ChildContainer
{
get
{
var scopeContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer;
if (scopeContainer == null)
HttpContext.Current.Items[HttpContextKey] = scopeContainer = _container.CreateChildContainer();
return scopeContainer;
}
}
...
}
As you can see here the child container is created first time the framework needs it and then it is recorded on the request object.
When the Service Locator is used it is important that the scoped container gets called whenever a new instance is needed. If the container is used directly, it means that all the code that needs to request a new instance has to be able to go to the current request object, obtain the reference to the scoped container and ask the instance. If we are in an ASP.NET app this is easier because we can use the DependencyResolver.Current
, which implements the Service Locator pattern and which with the above integration code will go to the Unity Container recorded on the current request. If we are using another implementation which wraps a dependency container like Common Service Locator does, you will need to set it up in a way that it uses the current container. The snippet below shows an example for the Common Service Locator.
...
private void ConfigureDependencyContainer()
{
Microsoft.Practices.ServiceLocation.ServiceLocator.SetLocatorProvider(() =>
{
var scopeContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer;
if (scopeContainer == null)
HttpContext.Current.Items[HttpContextKey] = scopeContainer = _container.CreateChildContainer();
return scopeContainer;
});
}
...
All the above work well when we are in a web application, but how can we do the same in a context where we do not have a request object (given by a framework) on which we can keep the scoped container? What if we want to scope our context to a custom operation? How can we make sure that whenever ServiceLocator.Current
is called from any class or any function in any thread, it will wrap over the current scoped container if the calling code is within an operation or it will go to the main container if it is outside of any operation? Such application examples may be:
- a windows service which listens on a TCP-IP socket and handles concurrently all the commands that come on the socket. The custom operation would be all the code that handles such a command.
- a console application which executes commands received through inline parameters. Here each command implementation would be part of the custom operation to which we would like to scope a child container.
- a desktop application, where we would like that all the code behind a screen to be part of an operation to dispose all the instances used while that screen was opened or used.
In all these cases we can create the scoped container and put it in a using statement that nests all the code within that operation. The difficulty comes in associating the scoped container with the operation. Where to keep it so all the code that runs within that operation uses it to build new instances. We need an object (like the request in the web app) which can keep this reference. That object should be available (through a static call) to any class or function on any thread which is within the operation. In short ServiceLocator.Current needs to wrap the scoped container of the current operation.
We can implement this by creating an OperationContext
class, which represents the context information of a custom operation. When it is built, it creates and stores a scoped container and it makes it available through a static getter. Here is a code snippet of this class
public class OperationContext : IDisposable
{
private readonly IDependencyContainer container;
private OperationContext()
{
container = ContextManager.GlobalContainer.CreateChildContainer();
}
public IServiceLocator ServiceLocator
{
get { return container.AsServiceLocator; }
}
public IDictionary Items
{
get
{
if (items == null)
items = new Hashtable();
return items;
}
}
public void Dispose()
{
DisposeItems();
IDisposable c = container as IDisposable;
if (c != null)
c.Dispose();
}
public static OperationContext Current
{
get { return ContextManager.Current; }
}
public static OperationContext CreateNew()
{
OperationContext operationContext = new OperationContext();
ContextManager.SwitchContext(operationContext);
return operationContext;
}
...
}
Our code which defines the scope will create a new OperationContext
when the operation starts and it will dispose it when the scope ends. We can do this with an using statement. The OperationContext.Current
gives access to it. It can be called from any class, function on any thread and it gives the current operation. ServiceLocator.Current
can wrap OperationContext.Current.ServiceLocator
and all existent code which we are nesting within this using statement shouldn’t be modified. This class makes sure that the current operation context information is thread static, but is it passed to new threads which are created within current operation. It also assures that when the operation ends all the disposables it holds (including the dependency injection container) are disposed.
The OperationContext
class implementation is inspired from the HttpContext
class. It uses a ContextManager
static class to manage the access to the storage of the context. The context store is abstracted by IContextStore
interface. Its implementation has to provide thread static storage for more operations that may exist simultaneous. When we are in a console application or in a windows service, its implementation is based on the CallContext
class. This assures that the context is passed along on any function call, and also to new threads which may be created from current one.
Having this, we can now define custom operations in any application in a easy way:
using(OperationContext.CreateNew())
{ //scope begins
// code that implements the operation
// ServiceLocator.Current wraps the scoped container created for this operation.
} // scope ends. OperationContext and all its content are disposed
The OperationContext
is an abstract solution for giving context information to any operation regardless of the type of application. When used in a web application the IContextStore
may be implemented over the HttpContext.Current
and the ASP.NET remains in control of managing the context of our operation (web request).
// IContextStore implementation for an ASP.NET app
public class HttpRequestContextStore : IContextStore
{
public object GetContext(string key)
{
return HttpContext.Current.Items[key];
}
public void SetContext(object context, string key)
{
HttpContext.Current.Items[key] = context;
}
// setup at app startup (Global.asax.cs)
protected void Application_Start()
{
...
ContextManager.SetContextStore(new HttpRequestContextStore());
}
// bind OperationContext with a web request
class RequestLifetimeHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, args) => OnBeginRequest();
context.EndRequest += (sender, e) => OnEndRequest();
}
private void OnBeginRequest()
{
OperationContext.CreateNew();
}
private void OnEndRequest()
{
OperationContext.Current.Dispose();
}
}
...
}
An integrated implementation of the OperationContext
, class can be found on iQuarc github repository for the AppBoot library. The OperationContext
there can be used in the same way in any .NET app. An isolated sample of the OperationContext
implementation code can be downloaded here:
To summarise, OperationContext
class gives us the means to easily achieve what we wanted: all the IDisposable
instances created within one defined scope to be disposed when the operation ends. It does this by using scoped dependency containers which are bound to the defined scope and are disposed when the scope ends. It also gives an abstract way to easily define such a scope when our code is in control or to bind it to one created and managed by a framework.
many examples and discussions like the above are included in my Code Design Training
We share our insights and experiences from working on client projects and teaching developers.
Our articles blend technical expertise with real-world challenges, offering a unique perspective on Code Design.
For us, Code Design means structuring code to ensure predictability and making it easy to manage and adapt long after it's written.