Scrutor icon indicating copy to clipboard operation
Scrutor copied to clipboard

Suggestion: Replace method

Open alexb5dh opened this issue 5 years ago • 1 comments

Scrutor API provides an easy way to actually replace service instead of decorating it. For example:

services.Decorate<ISeeder>((seeder, provider) => provider.CreateInstance<NoMigrationsAppSeeder>());

where CreateInstance is extension around ActivatorUtilities:

public static T CreateInstance<T>(this IServiceProvider serviceProvider, params object[] parameters) =>
ActivatorUtilities.CreateInstance<T>(serviceProvider, parameters);

and NoMigrationsAppSeeder uses default constructor.

Unfortunately this approach sometimes lead to stack overflow since Scrutor tries to resolve implementation instance even so it's not needed in this case.

My suggestion is to provide Replace extension methods which won't resolve previous implementation and provide callbacks with IServiceProvider only.

I understand that this could be done manually but existing Scrutor infrastructure makes it much easier to implement.

alexb5dh avatar Nov 25 '19 14:11 alexb5dh

Microsoft.Extensions.DependencyInjection.Abstractions has a Replace method.

public static IServiceCollection Replace(this IServiceCollection collection, ServiceDescriptor descriptor)

Replace only has one implementation accepting a ServiceDescriptor with no overloads. Would it be a good idea for Scrutor to add overloads for Replace? I don't know how it would handle lifetimes, it could either copy the previous lifetime or you could have ReplaceTransient,ReplaceScoped, etc. It might not be worth adding anything, I don't know how popular replace is.

public static bool TryReplace(this IServiceCollection collection, ServiceDescriptor descriptor);
public static void ReplaceWith<TService>(this IServiceCollection collection, Func<ServiceProvider, ServiceDescriptor> descriptor); // Let the user define the replacing provider for the matching implementation.
public static void Replace<TService>(this IServiceCollection collection, TService implementationService); // Replace with a ServiceDescriptor of the same lifetime?

TimothyMakkison avatar Jun 13 '22 14:06 TimothyMakkison