Ambient Context as a pattern has been around for a while, and although I’ve been making heavy use of it lately I haven’t really recognized it as a pattern until fairly recently. Like me, it is also very likely that you have also been making use of ambient context. If you’ve ever written code like this:

using (var scope = new TransactionScope())
using (var connection = new SqlConnection(...)
// Update the DB using connection

or have made use of the OperationContext object in WCF for example, then you too have also been making use of  ambient context. When I say ambient context as a pattern has been around for a while, I mean it has been for at least two or three years. I’ve found a few good blog posts from around that time that do a good job in describing the ambient context pattern. The Wandering Glitch has even gone as far as documenting ambient context in pattern language format and highlights several of its benefits, including the ability to define scopes, and also its use in providing cross cutting capabilities without having to introduce static variables or additional parameters into your method signatures. Mark Seemann also has a fantastic blog post on his old MSDN blog site which talks about using ambient context when implementing cross cutting aspects of code.

If you’re looking for an example then Lars Corneliussen has documented one of his implementationsand has also made the source code available. What’s interesting about Lars’ implementation is his introduction of a ThreadVariable<T> class which encapsulates the core of his ambient context implementation. Typical ambient context implementations use a static variable (marked with the ThreadStatic attribute) to represent the context. Lars’ approach wraps this detail up and hides it which is something that I’ll probably borrow from in my future implementations. Ambient context typically also makes use of a disposable scope class to define the context. This can be seen in the example shown above with the TransactionScope class. While the scope object is in “scope”, the underlying context is valid. When the scope class is disposed of then the context is also disposed of.

I’ve been using ambient context quite a lot recently with some work that I have been doing with AutoMapper. I’ve been mapping a common data model into various other forms, including other outward bound data models and also dictionaries (which are then serialized into streams as INI files). That’s right, you’ve guessed it; I’ve been interfacing with very old legacy applications. As part of this work I have been implementing custom type converters which are simply objects that implement an interface and are then plugged into the AutoMapper mapping infrastructure through a .ConvertUsing() method call. Although AutoMapper is a fantastic utility it’s quite difficult to pass extrinsic data into the mapping process. I guess the assumption is that you should have everything you need from the source data model. Despite this, combining ambient context with AutoMapper, I have been able to pass external data and other objects into my custom type converters by writing code like this:

using (new MappingContextScope())
MappingContext.Current.Formatter = new FooStreamFormatter();

var iniStream = Mapper.Map<FooDataModel, Stream>(dataModel);
SaveStream(iniStream, streamPath);

The custom type converters that may or may not be used in this mapping operation will also have access to the MappingContext by accessing MappingContext.Current. In this example, I need to apply some custom formatting within the stream being generated from a FooDataModel object (for example, dates, times, decimal point formatting and so on). Ambient context made this easy to implement and its structure lends itself well in helping to keep the code clean.

Tagged with: