My class library registers an IStartupFilter
(using a factory) with the ASP.NET Core container:
services.AddSingleton<IStartupFilter>(serviceProvider =>
ActivatorUtilities.CreateInstance<MyStartupFilter>(serviceProvider, new object[] { arg1, arg2 }));
That works.
But there are multiple ways to register the class library, so I don't want the filter to be added multiple times.
- If I use
AddSingleton
then the service is added, but could be added multiple times. - If I use
TryAddSingleton
then the service is not added at all - because the runtime already registers anIStartupFilter
of its own (HostFilteringStartupFilter
)
How can I "try add" a startup filter that uses a factory?
CodePudding user response:
you could add
services.RemoveAll<IStartupFilter>();
before your codes
also,you could try the method in ServiceCollectionDescriptorExtensions class:
public static IServiceCollection Replace(this IServiceCollection collection, ServiceDescriptor descriptor);
CodePudding user response:
Here's a dirty way to do it. If there's a better way please post your answer and I'll accept it.
var alreadyRegistered = services.Any(sd =>
sd.ServiceType == typeof(IStartupFilter) &&
sd.ImplementationFactory?.Target?.GetType() == this.GetType()
);
if (!alreadyRegistered)
{
services.AddSingleton<IStartupFilter>(serviceProvider =>
ActivatorUtilities.CreateInstance<MyStartupFilter>(serviceProvider, new object[] { arg1, arg2 }));
}
This fiddles with the service collection, which is an implementation detail of the container that should be left alone. And it assumes that the check and the registration occur in the same class. And it does not actually specify MyStartupFilter
, so you're not even sure it's doing the right thing, especially if that class adds other startup filters.
Dirty but works in simple cases.