The terminology from the question doesn't really match with the example code. The
Ambient Context is a pattern used to grab a dependency from any class in any module as easy as possible, without polluting every class to accept the dependency's interface, but still keeping the idea of inversion of control. Such dependencies are usually dedicated to logging, security, session management, transactions, caching, audit so to any cross cutting concern in that application. It's somehow annoying to add an
ITimeProvider to constructors and most of the time not all classes need all at the same time, so I understand your need.
What if the lifetime of the
ISession instance is different to the
ILogger one? Maybe the ISession instance should be created on every request and the ILogger once. So having all these dependencies governed by one object that is not the container itself doesn't look the right choice because of all these problems with lifetime management and localization and others described in this thread.
IAmbientContext in the question doesn't solve the problem of not polluting every constructor. You still have to use it in the constructor signature, sure, one time only this time.
So the easiest way is NOT use constructor injection or any other injection mechanism to deal with cross cutting dependencies, but using a static call. We are actually see this pattern quite often, implemented by the framework itself. Check Thread.CurrentPrincipal which is a static property that returns an implementation of the
IPrincipal interface. It's also settable so you can change the implementation if you like so, thus you aren't coupled to it.
MyCore looks now something like
public class MyCoreClass
public void BusinessFeature(string data)
This pattern and possible implementations have been described in detail by Mark Seemann in this article. There might be implementations that rely on the IoC container itself you use.
You want to avoid
AmbientContext.Current.Session for the same reasons as described above.
But you have other options to solve this problem: use decorators, dynamic interception if your container has this capability or AOP. The Ambient Context should be the last resort because of the fact its clients hide their dependencies through it. I would still use Ambient Context if the interface it really mimics my impulse to use a static dependency like
ConfigurationManager.AppSettings and this need raises quite often. But in the end the constructor injection might not be such a bad idea to get these ubiquitous dependencies.