Skip to content

Commit

Permalink
Add plumbing to support decorating keyed services
Browse files Browse the repository at this point in the history
  • Loading branch information
khellang committed Nov 15, 2023
1 parent 1a99cfb commit 4913f3a
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/Scrutor/ClosedTypeDecorationStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Scrutor;

internal sealed class ClosedTypeDecorationStrategy : DecorationStrategy
{
public ClosedTypeDecorationStrategy(Type serviceType, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) : base(serviceType)
public ClosedTypeDecorationStrategy(Type serviceType, string? serviceKey, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) : base(serviceType, serviceKey)
{
DecoratorType = decoratorType;
DecoratorFactory = decoratorFactory;
Expand All @@ -14,7 +14,7 @@ public ClosedTypeDecorationStrategy(Type serviceType, Type? decoratorType, Func<

private Func<object, IServiceProvider, object>? DecoratorFactory { get; }

public override bool CanDecorate(Type serviceType) => ServiceType == serviceType;
protected override bool CanDecorate(Type serviceType) => ServiceType == serviceType;

public override Func<IServiceProvider, object?, object> CreateDecorator(Type serviceType, string serviceKey)
{
Expand Down
24 changes: 15 additions & 9 deletions src/Scrutor/DecorationStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@ namespace Scrutor;

public abstract class DecorationStrategy
{
protected DecorationStrategy(Type serviceType)
protected DecorationStrategy(Type serviceType, string? serviceKey)
{
ServiceType = serviceType;
ServiceKey = serviceKey;
}

public Type ServiceType { get; }

public abstract bool CanDecorate(Type serviceType);
public string? ServiceKey { get; }

public virtual bool CanDecorate(ServiceDescriptor descriptor) =>
string.Equals(ServiceKey, descriptor.ServiceKey) && CanDecorate(descriptor.ServiceType);

protected abstract bool CanDecorate(Type serviceType);

public abstract Func<IServiceProvider, object?, object> CreateDecorator(Type serviceType, string serviceKey);

internal static DecorationStrategy WithType(Type serviceType, Type decoratorType) =>
Create(serviceType, decoratorType, decoratorFactory: null);
internal static DecorationStrategy WithType(Type serviceType, string? serviceKey, Type decoratorType) =>
Create(serviceType, serviceKey, decoratorType, decoratorFactory: null);

internal static DecorationStrategy WithFactory(Type serviceType, Func<object, IServiceProvider, object> decoratorFactory) =>
Create(serviceType, decoratorType: null, decoratorFactory);
internal static DecorationStrategy WithFactory(Type serviceType, string? serviceKey, Func<object, IServiceProvider, object> decoratorFactory) =>
Create(serviceType, serviceKey, decoratorType: null, decoratorFactory);

protected static Func<IServiceProvider, object?, object> TypeDecorator(Type serviceType, string serviceKey, Type decoratorType)
{
Expand All @@ -38,13 +44,13 @@ internal static DecorationStrategy WithFactory(Type serviceType, Func<object, IS
return decoratorFactory(instanceToDecorate, serviceProvider);
};

private static DecorationStrategy Create(Type serviceType, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory)
private static DecorationStrategy Create(Type serviceType, string? serviceKey, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory)
{
if (serviceType.IsOpenGeneric())
{
return new OpenGenericDecorationStrategy(serviceType, decoratorType, decoratorFactory);
return new OpenGenericDecorationStrategy(serviceType, serviceKey, decoratorType, decoratorFactory);
}

return new ClosedTypeDecorationStrategy(serviceType, decoratorType, decoratorFactory);
return new ClosedTypeDecorationStrategy(serviceType, serviceKey, decoratorType, decoratorFactory);
}
}
4 changes: 2 additions & 2 deletions src/Scrutor/OpenGenericDecorationStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Scrutor;

public class OpenGenericDecorationStrategy : DecorationStrategy
{
public OpenGenericDecorationStrategy(Type serviceType, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) : base(serviceType)
public OpenGenericDecorationStrategy(Type serviceType, string? serviceKey, Type? decoratorType, Func<object, IServiceProvider, object>? decoratorFactory) : base(serviceType, serviceKey)
{
DecoratorType = decoratorType;
DecoratorFactory = decoratorFactory;
Expand All @@ -14,7 +14,7 @@ public OpenGenericDecorationStrategy(Type serviceType, Type? decoratorType, Func

private Func<object, IServiceProvider, object>? DecoratorFactory { get; }

public override bool CanDecorate(Type serviceType) =>
protected override bool CanDecorate(Type serviceType) =>
serviceType.IsGenericType
&& !serviceType.IsGenericTypeDefinition
&& serviceType.GetGenericTypeDefinition() == ServiceType.GetGenericTypeDefinition()
Expand Down
10 changes: 5 additions & 5 deletions src/Scrutor/ServiceCollectionExtensions.Decoration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static IServiceCollection Decorate(this IServiceCollection services, Type
Preconditions.NotNull(serviceType, nameof(serviceType));
Preconditions.NotNull(decoratorType, nameof(decoratorType));

return services.Decorate(DecorationStrategy.WithType(serviceType, decoratorType));
return services.Decorate(DecorationStrategy.WithType(serviceType, serviceKey: null, decoratorType));
}

/// <summary>
Expand All @@ -73,7 +73,7 @@ public static bool TryDecorate(this IServiceCollection services, Type serviceTyp
Preconditions.NotNull(serviceType, nameof(serviceType));
Preconditions.NotNull(decoratorType, nameof(decoratorType));

return services.TryDecorate(DecorationStrategy.WithType(serviceType, decoratorType));
return services.TryDecorate(DecorationStrategy.WithType(serviceType, serviceKey: null, decoratorType));
}

/// <summary>
Expand Down Expand Up @@ -199,7 +199,7 @@ public static IServiceCollection Decorate(this IServiceCollection services, Type
Preconditions.NotNull(serviceType, nameof(serviceType));
Preconditions.NotNull(decorator, nameof(decorator));

return services.Decorate(DecorationStrategy.WithFactory(serviceType, decorator));
return services.Decorate(DecorationStrategy.WithFactory(serviceType, serviceKey: null, decorator));
}

/// <summary>
Expand All @@ -217,7 +217,7 @@ public static bool TryDecorate(this IServiceCollection services, Type serviceTyp
Preconditions.NotNull(serviceType, nameof(serviceType));
Preconditions.NotNull(decorator, nameof(decorator));

return services.TryDecorate(DecorationStrategy.WithFactory(serviceType, decorator));
return services.TryDecorate(DecorationStrategy.WithFactory(serviceType, serviceKey: null, decorator));
}

/// <summary>
Expand Down Expand Up @@ -252,7 +252,7 @@ public static bool TryDecorate(this IServiceCollection services, DecorationStrat
{
var serviceDescriptor = services[i];

if (IsDecorated(serviceDescriptor) || !strategy.CanDecorate(serviceDescriptor.ServiceType))
if (IsDecorated(serviceDescriptor) || !strategy.CanDecorate(serviceDescriptor))
{
continue;
}
Expand Down

0 comments on commit 4913f3a

Please sign in to comment.