So I have this Simple Injector IoC wire up code
container.RegisterSingleton<IMsgProcessor, PrometheusTickerPublisher>();
container.RegisterSingleton<ICollector, UpdatesPerSecondDataCollector>();
And when I try and run my app I am getting this error message
A lifestyle mismatch is encountered. PrometheusTickerPublisher (Singleton) depends on UpdatesPerSecondDataCollector (Transient). Lifestyle mismatches can cause concurrency bugs in your application. Please see https://simpleinjector.org/dialm to understand this problem and how to solve it.
I don't get this at all. Both items are registered as singletons. I then changed the registration to this, to see if I could be more explicit about it being a singleton
container.RegisterSingleton<IMsgProcessor, PrometheusTickerPublisher>();
container.AddRegistration(typeof(ICollector), CreateCollectorRegistration(container));
internal static Registration CreateCollectorRegistration(Container container)
{
return
Lifestyle.Singleton.CreateRegistration<ICollector>(
() =>
{
var timeProvider = container.GetInstance<ITimeProvider>();
return new UpdatesPerSecondDataCollector(timeProvider);
}, container);
}
But this gives the same error
At this point I am completely lost, Any ideas
Calling Container.Verify()
at the end of the registration process will check the container's health. If you do that, it would give you even more feedback:
The configuration is invalid. The following diagnostic warnings were reported:
-[Lifestyle Mismatch] PrometheusTickerPublisher (Singleton) depends on UpdatesPerSecondDataCollector (Transient).
-[Short Circuited Dependency] PrometheusTickerPublisher might incorrectly depend on unregistered type UpdatesPerSecondDataCollector (Transient) instead of ICollector (Singleton).
-[Ambiguous Lifestyles] The registration for UpdatesPerSecondDataCollector (Transient) maps to the same implementation (UpdatesPerSecondDataCollector) as the registration for ICollector (Singleton) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.
-[Ambiguous Lifestyles] The registration for ICollector (Singleton) maps to the same implementation (UpdatesPerSecondDataCollector) as the registration for UpdatesPerSecondDataCollector (Transient) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance. See the Error property for detailed information about the warnings.
Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.
The most interesting part here is the Short Circuited Dependency warning:
-[Short Circuited Dependency]
PrometheusTickerPublisher
might incorrectly depend on unregistered typeUpdatesPerSecondDataCollector
(Transient) instead ofICollector
(Singleton).
In other words, Simple Injector detects that you registered UpdatesPerSecondDataCollector
through its ICollector
as Singleton
, but you are circumventing that ICollector
registration by depending directly on the UpdatesPerSecondDataCollector
implementation instead. This is called short-circuited, because instead of using the ICollector
registration, you go directly to the (unregistered) implementation. This might cause all sorts of problems.
Because there is no explicit registration for UpdatesPerSecondDataCollector
, Simple Injector will implicitly register it for you, and it uses the Transient
lifestyle (unless you specify otherwise). The registration for ICollector
, however, is a Singleton
, so that will likely cause problems. This is again noted in the Ambiguous Lifestyles warning:
-[Ambiguous Lifestyles] The registration for UpdatesPerSecondDataCollector (Transient) maps to the same implementation (UpdatesPerSecondDataCollector) as the registration for ICollector (Singleton) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.
Without calling Verify
, all these issues stay undetected. The only verification Simple Injector does when resolving a type is the Lifestyle Mismatch, which is why you only got the following error:
A lifestyle mismatch is encountered. PrometheusTickerPublisher (Singleton) depends on UpdatesPerSecondDataCollector (Transient).
Long story short, you didn't register UpdatesPerSecondDataCollector
by itself, but only by its ICollector
abstraction, causing Simple injector to implicitly make a Transient
registration for UpdatesPerSecondDataCollector
on your behalf. Because this registration is Transient
, Simple Injector blocked the injection of it into the Singleton
class PrometheusTickerPublisher
. If you would have called Container.Verify()
, there would be a very detailed problem description of what is going wrong, which is much more than just a simple Lifestyle Mismatch.