From the Autofac wiki page on instance scopes ...
Up vote 0 down vote favorite share g+ share fb share tw.
I am having a problem resolving singleton components in Autofac and wondering if Autofac is behaving correctly or if this is a genuine bug. The way I understand Autofac is working is that when you register a singleton component, that registration gets "pulled" to the root container so that anything that resolves that component will resolve the same instance. So, I am wondering if that same mechanism should come into play when registering the singleton component in separate child scopes.
I'll let the code speak for itself: public class ChildSingletonScopeTest { readonly IContainer container; readonly ILifetimeScope scope1, scope2, childScope1; public ChildSingletonScopeTest() { var builder = new ContainerBuilder(); container = builder.Build(); scope1 = container. BeginLifetimeScope(ConfigureTenant); scope2 = container. BeginLifetimeScope(ConfigureTenant); childScope1 = scope1.
BeginLifetimeScope(); } void ConfigureTenant(ContainerBuilder builder) { builder.RegisterType().As().SingleInstance(); } Xunit. Fact /* this test fails */ public void should_resolve_single_instance_for_each_tenant_scope() { var instance1 = scope1.Resolve(); var instance2 = scope2.Resolve(); Xunit.Assert. Equal(instance1, instance2); } Xunit.
Fact /* this test passes */ public void should_resolve_single_instance_down_child_scope_hierarchy() { var instance1 = scope1.Resolve(); var instance2 = childScope1.Resolve(); Xunit.Assert. Equal(instance1, instance2); } } interface ITesting { } class Testing : ITesting { public override string ToString() { return GetHashCode().ToString(); } } The reason that I am trying to do something crazy like this comes down to the way we are implementing multitenancy in our web app. Without getting too bogged down in the details, we have a requirement to be able to programmatically "switch" tenants in the middle of a web request.
The way we do this is by nesting the tenant scopes under each disposable request scope. However, tenant-specific singleton registrations are not resolving the same instance for the same tenant across different requests. So, I am wondering if this is a bug in the way Autofac is handling these singleton registrations OR if I need to change the way I am dealing with singleton components in the tenant scopes.
Autofac multi-tenant link|improve this question asked Mar 29 at 15:37Chad333.
From the Autofac wiki page on instance scopes... Using single instance scope, one instance is returned from all requests in the parent and all nested containers. Which means if you have nested scopes like this... container scope-1 scope-2 Then if you register a singleton in "scope-1" then when you resolve it in "scope-2" you'll get the same singleton. On the other hand, if you try to resolve it in the container, you won't get anything because it wasn't registered there - the registrations "inherit" down the tree, not up, as your tests prove out.
There is a nice primer on Autofac lifetime scopes and component resolution on Nick Blumhardt's blog. One confusing thing you might see there is a mention of how singleton-scoped components get resolved if the registration isn't in the current scope. Say you register a singleton in "scope-1" and that singleton has a dependency.
Further, say the dependency is registered in both "scope-1" and "scope-2. " Now you resolve the singleton from "scope-2. " Since the singleton is registered in "scope-1" it will resolve its dependencies from "scope-1" instead of using your override in "scope-2" - because once "scope-2" ends, the singleton still has to stick around in "scope-1" for others to consume.
In other areas of your scenario, you may also end up running into a "last-in-wins" thing, too. If you register a singleton in the "container" and then another in "scope-1," when you resolve from "scope-2" you'll get the one registered in "scope-1," not the one from the root. However, you should also be able to resolve all of them, like... scope.
Resolve>(); If you resolve an IEnumerable of your component, you get all of the registered components, not just the last one you registered. I suppose that's a long way of saying it's not a bug, that's how Autofac works. If you're doing multitenancy with Autofac, have you looked at AutofacContrib.
Multitenant? It's one of the contributed libraries that has native support for things like tenant-based singletons. There is a wiki page on Autofac for that, too.
You can configure your application-level defaults and then tenant-specific overrides. You can also do things like... containerBuilder.RegisterType().As(). InstancePerTenant(); ...which makes root-level registration of tenant singletons pretty simple.
There isn't a NuGet package for the contrib libraries in Autofac yet (we're working on it) so you'll have to go to the site and manually download, but it might help solve your problem. Full disclosure: I wrote AutofacContrib.Multitenant.
Thanks for the informative answer. We are actually using the AutofacContrib. Multitenant project, just without certain pieces.
We needed to be able to "switch" tenants during a request and hence had to invert the container hierarchy.e.g. Each tenant scope is created as a child of the current request scope instead of the other way around so that switching between tenants keeps us underneath the original request scope. – Chad Apr 2 at 18:11.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.