I\'m try to supply a different service to some tagged lifetime scopes in AutoFac, but can\'t seem to get the hang of it.
I\'ve tried using the custom lifetime from Insta
The following extension can be used to automate tdragon's answer. It also solves the nested scope problem.
public static class RegistrationBuilderExtensions
{
public static IRegistrationBuilder
RegisterScopeResolver(this ContainerBuilder containerBuilder)
{
IRegistrationBuilder defineServiceScopes =
containerBuilder.Register(componentContext =>
{
var scope = componentContext.Resolve();
var registrations = componentContext.ComponentRegistry.RegistrationsFor(new TypedService(typeof(TLimit))).ToList();
Type activatorLimitType = registrations.Where(x => x.Lifetime is MatchingScopeLifetime).SingleOrDefault(x =>
(x.Lifetime as MatchingScopeLifetime).TagsToMatch.Contains(scope.Tag))?.Activator.LimitType;
if (activatorLimitType == null)
{
activatorLimitType = registrations.Single(x =>
{
return x.Lifetime.GetType() != typeof(MatchingScopeByFirstOccurenceLifetime) &&
x.Lifetime.GetType() != typeof(MatchingScopeLifetime);
})
.Activator
.LimitType;
}
return (TLimit) componentContext
.Resolve(activatorLimitType);
});
defineServiceScopes.RegistrationData.Sharing = InstanceSharing.Shared;
defineServiceScopes.RegistrationData.Lifetime = new MatchingScopeByFirstOccurenceLifetime();
return defineServiceScopes;
}
private class MatchingScopeByFirstOccurenceLifetime : IComponentLifetime
{
public ISharingLifetimeScope FindScope(ISharingLifetimeScope mostNestedVisibleScope)
{
if (mostNestedVisibleScope == null)
throw new ArgumentNullException(nameof(mostNestedVisibleScope));
var next = mostNestedVisibleScope;
while (next != null)
{
if (next.ComponentRegistry
.RegistrationsFor(new TypedService(typeof(TLimit)))
.Select(x => x.Lifetime)
.OfType()
.Any(x => x.TagsToMatch.Contains(next.Tag)))
return next;
next = next.ParentLifetimeScope;
}
return mostNestedVisibleScope.RootLifetimeScope;
}
}
}
Usage
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType().As().InstancePerMatchingLifetimeScope("A").AsSelf();
containerBuilder.RegisterType().As().InstancePerMatchingLifetimeScope("B").AsSelf();
containerBuilder.RegisterScopeResolver();
var container = containerBuilder.Build();
using (var lifetimeScope = container.BeginLifetimeScope("A"))
{
Console.WriteLine(lifetimeScope.Resolve());
using (var nestedLifetimeScope = lifetimeScope.BeginLifetimeScope())
{
Console.WriteLine(nestedLifetimeScope.Resolve());
}
}
using (var lifetimeScope = container.BeginLifetimeScope("B"))
{
Console.WriteLine(lifetimeScope.Resolve());
using (var nestedLifetimeScope = lifetimeScope.BeginLifetimeScope())
{
Console.WriteLine(nestedLifetimeScope.Resolve());
}
}
Result
BaseA Id:69fc4258-6920-42a6-8404-94d11ce46064
BaseA Id:69fc4258-6920-42a6-8404-94d11ce46064
BaseB Id:53d45071-5810-4358-ae87-bf250f5e3f02
BaseB Id:53d45071-5810-4358-ae87-bf250f5e3f02