Created
June 28, 2023 20:09
-
-
Save AntonC9018/835650beb22cd4bd10646dd9e257ef06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#nullable enable | |
using Microsoft.Extensions.DependencyInjection; | |
public static class ServiceRegistrationHelper | |
{ | |
/// <summary> | |
/// Registers the given implementation type under all implementations of a generic service, | |
/// implemented by the given implementation type. | |
/// </summary> | |
/// <returns>True if at least one implementation has been registered</returns> | |
public static bool RegisterImplementationsOfGenericService<TImplementation>( | |
this IServiceCollection services, | |
Type unboundServiceType, | |
ServiceLifetime lifetime) | |
where TImplementation : notnull | |
{ | |
Type implementationType = typeof(TImplementation); | |
using var implementedServices = implementationType | |
.GetInterfaces() | |
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == unboundServiceType) | |
.GetEnumerator(); | |
if (!implementedServices.MoveNext()) | |
return false; | |
var firstImpl = implementedServices.Current; | |
// Register only a single implementation. | |
if (!implementedServices.MoveNext()) | |
{ | |
var descriptor = new ServiceDescriptor( | |
firstImpl, | |
implementationType, | |
lifetime); | |
services.Add(descriptor); | |
return true; | |
} | |
// Multiple implementations in one class. | |
{ | |
var descriptor = new ServiceDescriptor( | |
implementationType, | |
implementationType, | |
lifetime); | |
services.Add(descriptor); | |
} | |
void AddImpl(Type implementedInterface) | |
{ | |
var descriptor = new ServiceDescriptor( | |
implementedInterface, | |
static sp => sp.GetRequiredService<TImplementation>(), | |
lifetime); | |
services.Add(descriptor); | |
} | |
AddImpl(firstImpl); | |
do | |
{ | |
AddImpl(implementedServices.Current); | |
} while (implementedServices.MoveNext()); | |
return true; | |
} | |
public static IServiceCollection RegisterRequiredImplementationsOfGenericService<T>( | |
this IServiceCollection services, | |
Type markerServiceType, | |
Type unboundServiceType, | |
ServiceLifetime lifetime) | |
where T : notnull | |
{ | |
bool registered = services.RegisterImplementationsOfGenericService<T>( | |
unboundServiceType, lifetime); | |
if (!registered) | |
{ | |
throw new InvalidOperationException( | |
$"{markerServiceType.Name} should only be inherited via {unboundServiceType.Name}"); | |
} | |
return services; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment