Resolve component in both tagged scope and untagged scope

前端 未结 2 1885
轻奢々
轻奢々 2021-01-23 04:01

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

2条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-23 04:47

    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
    

提交回复
热议问题