Skip to content

Commit e77e0f2

Browse files
ripebananaskhellang
authored andcommitted
Extended ILifetimeSelector with a new WithLifetime method that accepts a Func<Type, ServiceLifetime> parameter, i.e. a function that maps the implementation type to the service lifetime
1 parent 1109c88 commit e77e0f2

File tree

4 files changed

+32
-9
lines changed

4 files changed

+32
-9
lines changed

src/Scrutor/ILifetimeSelector.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Extensions.DependencyInjection;
1+
using System;
2+
using Microsoft.Extensions.DependencyInjection;
23

34
namespace Scrutor;
45

@@ -23,4 +24,9 @@ public interface ILifetimeSelector : IServiceTypeSelector
2324
/// Registers each matching concrete type with the specified <paramref name="lifetime"/>.
2425
/// </summary>
2526
IImplementationTypeSelector WithLifetime(ServiceLifetime lifetime);
27+
28+
/// <summary>
29+
/// Registers each matching concrete type with the specified <paramref name="lifetime"/>.
30+
/// </summary>
31+
IImplementationTypeSelector WithLifetime(Func<Type, ServiceLifetime> lifetime);
2632
}

src/Scrutor/LifetimeSelector.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public LifetimeSelector(ServiceTypeSelector inner, IEnumerable<TypeMap> typeMaps
2121

2222
private IEnumerable<TypeFactoryMap> TypeFactoryMaps { get; }
2323

24-
public ServiceLifetime? Lifetime { get; set; }
24+
public Func<Type, ServiceLifetime>? Lifetime { get; set; }
2525

2626
public IImplementationTypeSelector WithSingletonLifetime()
2727
{
@@ -37,11 +37,17 @@ public IImplementationTypeSelector WithTransientLifetime()
3737
{
3838
return WithLifetime(ServiceLifetime.Transient);
3939
}
40-
4140
public IImplementationTypeSelector WithLifetime(ServiceLifetime lifetime)
4241
{
4342
Preconditions.IsDefined(lifetime, nameof(lifetime));
4443

44+
return WithLifetime(_ => lifetime);
45+
}
46+
47+
public IImplementationTypeSelector WithLifetime(Func<Type, ServiceLifetime> lifetime)
48+
{
49+
Preconditions.NotNull(lifetime, nameof(lifetime));
50+
4551
Inner.PropagateLifetime(lifetime);
4652

4753
return this;
@@ -205,7 +211,7 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? strat
205211
{
206212
strategy ??= RegistrationStrategy.Append;
207213

208-
var lifetime = Lifetime ?? ServiceLifetime.Transient;
214+
var serviceLifetimes = new Dictionary<Type, ServiceLifetime>();
209215

210216
foreach (var typeMap in TypeMaps)
211217
{
@@ -218,7 +224,7 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? strat
218224
throw new InvalidOperationException($@"Type ""{implementationType.ToFriendlyName()}"" is not assignable to ""${serviceType.ToFriendlyName()}"".");
219225
}
220226

221-
var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);
227+
var descriptor = new ServiceDescriptor(serviceType, implementationType, GetOrAddLifetime(serviceLifetimes, implementationType));
222228

223229
strategy.Apply(services, descriptor);
224230
}
@@ -228,10 +234,17 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? strat
228234
{
229235
foreach (var serviceType in typeFactoryMap.ServiceTypes)
230236
{
231-
var descriptor = new ServiceDescriptor(serviceType, typeFactoryMap.ImplementationFactory, lifetime);
237+
var descriptor = new ServiceDescriptor(serviceType, typeFactoryMap.ImplementationFactory, GetOrAddLifetime(serviceLifetimes, typeFactoryMap.ImplementationType));
232238

233239
strategy.Apply(services, descriptor);
234240
}
235241
}
236242
}
243+
244+
private ServiceLifetime GetOrAddLifetime(Dictionary<Type, ServiceLifetime> serviceLifetimes, Type implementationType)
245+
{
246+
return serviceLifetimes.TryGetValue(implementationType, out var lifetime)
247+
? lifetime
248+
: (serviceLifetimes[implementationType] = Lifetime?.Invoke(implementationType) ?? ServiceLifetime.Transient);
249+
}
237250
}

src/Scrutor/ServiceTypeSelector.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public ILifetimeSelector AsSelfWithInterfaces(Func<Type, bool> predicate)
7171

7272
return AddSelector(
7373
Types.Select(t => new TypeMap(t, new[] { t })),
74-
Types.Select(t => new TypeFactoryMap(x => x.GetRequiredService(t), Selector(t, predicate))));
74+
Types.Select(t => new TypeFactoryMap(x => x.GetRequiredService(t), Selector(t, predicate), t)));
7575

7676
static IEnumerable<Type> Selector(Type type, Func<Type, bool> predicate)
7777
{
@@ -209,7 +209,7 @@ public IServiceTypeSelector AddClasses(Action<IImplementationTypeFilter> action,
209209

210210
#endregion
211211

212-
internal void PropagateLifetime(ServiceLifetime lifetime)
212+
internal void PropagateLifetime(Func<Type, ServiceLifetime> lifetime)
213213
{
214214
foreach (var selector in Selectors.OfType<LifetimeSelector>())
215215
{

src/Scrutor/TypeFactoryMap.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ namespace Scrutor;
55

66
internal struct TypeFactoryMap
77
{
8-
public TypeFactoryMap(Func<IServiceProvider, object> implementationFactory, IEnumerable<Type> serviceTypes)
8+
public TypeFactoryMap(Func<IServiceProvider, object> implementationFactory, IEnumerable<Type> serviceTypes, Type implementationType)
99
{
1010
ImplementationFactory = implementationFactory;
1111
ServiceTypes = serviceTypes;
12+
ImplementationType = implementationType;
1213
}
1314

1415
public Func<IServiceProvider, object> ImplementationFactory { get; }
1516

1617
public IEnumerable<Type> ServiceTypes { get; }
18+
19+
public Type ImplementationType { get; }
20+
1721
}

0 commit comments

Comments
 (0)