Fairly easy. Problem is, of course that there’s no way you can test a class that uses this singleton now. The easy thing that you might be tempted to do is to just make the setter internal and starting replacing the singleton clock with mocks of it. Problem is, as you may have guessed, that now the tests cannot be run in multiple threads simultaneously. You have made no provisions for shielding changes across threads, so if one test setups up the singleton with a mock with certain values, and another goes and changes it before the asserts get through, you’ll be seeing intermittent failures on random tests when run together, but no single failure when run individually.

Being such a common problem, the .NET framework provides a few ways to work around that, via a mechanism called Thread Local Storage (or TLS). Joe Albahari provides a great summary of the available options, so make sure you read that link. In summary, they are:

These options have slightly different performance characteristics (in my tests, ThreadStatic is fastest and the other two about 5x slower than that). However, they all share a very serious limitation, that was highlighted by Scott ages ago, back in 2003. They simply don’t work if what you need is per-context state, such as per web request, per test, essentially, per Call Context. Some call this the Ambient Context pattern, but its essence in .NET is the Logical Call Context, thoroughly dissected by Jeffrey Richter in a blog post.

Given its misleading MSDN summary, and its location with the namespace System.Runtime.Remoting.Messaging, it’s not surprising that developers quickly dismiss it as a valid (and much better as we’ll see!) alternative. A logical call context flows as a thread-like state bag, but it’s not limited to a single thread. In fact, even the new threading Tasks library honors this capability, and the most prominent use of this in .NET is in WCF E2E Tracing, which uses the CorrelationManager.ActivityId, which is persisted in the logical call context and flows even across AppDomains.

You basically use CallContext.LogicalGetData and LogicalSetData instead of the Thread.SetData/GetData from the example above. It is, however, a bit cumbersome, and I just wish we had something like ThreadLocal<T> to leverage for this “smart singleton” (or “ambient singleton”) capability.

It is safe to set the value of the singleton in multiple threads simultaneously, and the value you set will be preserved in the entire call chain, even if the test or code under test spawns new threads via the thread pool or the task pool (which ultimately also uses the thread pool by default).

There is also a static AmbientSingleton.Create factory method with a couple overloads, to cut on the generic parameters noise.

The entire source for the class is very straightforward, as you’d expect:

As you can see, the Ambient Singleton behaves like a regular singleton, without the overhead of per-thread initialization, when it’s not needed. This is another drawback of the TLS approaches: if the object initialization is expensive, you’ll be paying for that once per thread. In the ambient singleton, however, only when a particular call context requires a different value for the singleton, the added behavior kicks in. In my tests this approach is the closest to the speed of [ThreadStatic], measuring only about 1.8x the ThreadStatic approach (compared with 5x for the ThreadLocal<T> and Thread data). All in all, a very compelling way of implementing singletons, when they are unavoidable (although you could say there’s always another way of doing it , but that’s another post).

You can install the nuget package to get the source AmbientSingleton<T> class, which is partial and defaults to internal, as you’d typically not expose it as a public type in your libraries, and is rather an internal implementation detail of your singletons. You can of course create another partial of it and make it public if you wish. It’s fully documented, and lives in the System namespace.

In order to keep your code coverage goals, you can also install the xUnit tests which provide 100% coverage for this source.

I wish there was more documentation and guidance on how to use all of the different contexts available to a .net developer. ExecutionContext, CompressedStack and others come to mind. Almost nobody used them.

Interesting, and two thoughts for consideration:
1) CallContext is considered a ‘legacy technology’ in .NET 4.5.
2) The note about HttpContext is interesting, as that is what has lead me searching. In my case, I need a thread-static which I can use within my business-logic, which sometimes has an HttpContext (usual ASP.NET life-cycle complciated by thread-agility), and sometimes does not have an HttpContext (e.g. unit-tests, service-process independent of IIS). I’ll be pursuing a dependency-injection-style-solution, i.e. I’ll define an interface and more than two implementations (one with [ThreadStatic] and one with HttpContext.Current.Items).

I thought this was just what the doctor ordered for having a TraceId available throughout the entire call stack… but now I’m having difficulties and I’m not sure why. I use AmbientSingleton where TraceContex is my own class with 3 string properties (internal setters). I have a Handler that fires for every web request, checks for a TraceId header and plugs that value into the TraceContext.TraceId. This TraceContextHandler inherits from DelegatingHandler and as such returns base.SendAsynch(…). This worked perfectly in my Framework app with a bunch of Project references, so I built some Nuget packages and installed them into an API based on our Framework. When testing this app, the TraceId was always null in the log data. I changed the AmbientSingleton class to implement ILogicalThreadAffinative, changed the public T Value get/set to use CallContext.LogicalSetData/GetData and now it works. I did this based on Stephen Cleary’s blog (http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html) in which he stated:

“There is a solution for this problem: the “logical call context”, which you can access by CallContext.LogicalGetData and CallContext.LogicalSetData. The regular call context (CallContext.GetData and CallContext.SetData) acts just like thread-local storage, which of course doesn’t work for async methods.”

Thoughts? Possible issues I may be facing? I’m assuming the implementation I have now will essentially create/use a TraceId for the entire request, but only one request. New requests will use/create their own traceId value and they won’t leak across requests.