diff --git a/src/Scrutor/ILifetimeSelector.cs b/src/Scrutor/ILifetimeSelector.cs index 344424b1..ba7771a2 100644 --- a/src/Scrutor/ILifetimeSelector.cs +++ b/src/Scrutor/ILifetimeSelector.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using Microsoft.Extensions.DependencyInjection; namespace Scrutor; @@ -23,4 +24,9 @@ public interface ILifetimeSelector : IServiceTypeSelector /// Registers each matching concrete type with the specified . /// IImplementationTypeSelector WithLifetime(ServiceLifetime lifetime); + + /// + /// Registers each matching concrete type with the specified . + /// + IImplementationTypeSelector WithLifetime(Func lifetime); } diff --git a/src/Scrutor/LifetimeSelector.cs b/src/Scrutor/LifetimeSelector.cs index 51e2ea46..0c224902 100644 --- a/src/Scrutor/LifetimeSelector.cs +++ b/src/Scrutor/LifetimeSelector.cs @@ -21,7 +21,7 @@ public LifetimeSelector(ServiceTypeSelector inner, IEnumerable typeMaps private IEnumerable TypeFactoryMaps { get; } - public ServiceLifetime? Lifetime { get; set; } + public Func? Lifetime { get; set; } public IImplementationTypeSelector WithSingletonLifetime() { @@ -37,11 +37,17 @@ public IImplementationTypeSelector WithTransientLifetime() { return WithLifetime(ServiceLifetime.Transient); } - public IImplementationTypeSelector WithLifetime(ServiceLifetime lifetime) { Preconditions.IsDefined(lifetime, nameof(lifetime)); + return WithLifetime(_ => lifetime); + } + + public IImplementationTypeSelector WithLifetime(Func lifetime) + { + Preconditions.NotNull(lifetime, nameof(lifetime)); + Inner.PropagateLifetime(lifetime); return this; @@ -205,7 +211,7 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? strat { strategy ??= RegistrationStrategy.Append; - var lifetime = Lifetime ?? ServiceLifetime.Transient; + var serviceLifetimes = new Dictionary(); foreach (var typeMap in TypeMaps) { @@ -218,7 +224,7 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? strat throw new InvalidOperationException($@"Type ""{implementationType.ToFriendlyName()}"" is not assignable to ""${serviceType.ToFriendlyName()}""."); } - var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime); + var descriptor = new ServiceDescriptor(serviceType, implementationType, GetOrAddLifetime(serviceLifetimes, implementationType)); strategy.Apply(services, descriptor); } @@ -228,10 +234,17 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? strat { foreach (var serviceType in typeFactoryMap.ServiceTypes) { - var descriptor = new ServiceDescriptor(serviceType, typeFactoryMap.ImplementationFactory, lifetime); + var descriptor = new ServiceDescriptor(serviceType, typeFactoryMap.ImplementationFactory, GetOrAddLifetime(serviceLifetimes, typeFactoryMap.ImplementationType)); strategy.Apply(services, descriptor); } } } + + private ServiceLifetime GetOrAddLifetime(Dictionary serviceLifetimes, Type implementationType) + { + return serviceLifetimes.TryGetValue(implementationType, out var lifetime) + ? lifetime + : (serviceLifetimes[implementationType] = Lifetime?.Invoke(implementationType) ?? ServiceLifetime.Transient); + } } diff --git a/src/Scrutor/ServiceTypeSelector.cs b/src/Scrutor/ServiceTypeSelector.cs index c850d5e9..51ca8320 100644 --- a/src/Scrutor/ServiceTypeSelector.cs +++ b/src/Scrutor/ServiceTypeSelector.cs @@ -71,7 +71,7 @@ public ILifetimeSelector AsSelfWithInterfaces(Func predicate) return AddSelector( Types.Select(t => new TypeMap(t, new[] { t })), - Types.Select(t => new TypeFactoryMap(x => x.GetRequiredService(t), Selector(t, predicate)))); + Types.Select(t => new TypeFactoryMap(x => x.GetRequiredService(t), Selector(t, predicate), t))); static IEnumerable Selector(Type type, Func predicate) { @@ -209,7 +209,7 @@ public IServiceTypeSelector AddClasses(Action action, #endregion - internal void PropagateLifetime(ServiceLifetime lifetime) + internal void PropagateLifetime(Func lifetime) { foreach (var selector in Selectors.OfType()) { diff --git a/src/Scrutor/TypeFactoryMap.cs b/src/Scrutor/TypeFactoryMap.cs index d26e0273..f2c5edc2 100644 --- a/src/Scrutor/TypeFactoryMap.cs +++ b/src/Scrutor/TypeFactoryMap.cs @@ -5,13 +5,17 @@ namespace Scrutor; internal struct TypeFactoryMap { - public TypeFactoryMap(Func implementationFactory, IEnumerable serviceTypes) + public TypeFactoryMap(Func implementationFactory, IEnumerable serviceTypes, Type implementationType) { ImplementationFactory = implementationFactory; ServiceTypes = serviceTypes; + ImplementationType = implementationType; } public Func ImplementationFactory { get; } public IEnumerable ServiceTypes { get; } + + public Type ImplementationType { get; } + }