I have interface IOrder<T> and FurnitureOrder<T> implements it
I need to register multiple implementations like this
services.AddSingleton(IOrder<Chair>, FurnitureOrder<Chair>())
services.AddSingleton(IOrder<Table>, FurnitureOrder<Table>())
Now I have need to retrieve all IOrder services and the types(e.g chair, table) to do some background work on it.
Can I get it using GetServices API?
if not possible, Please suggest if design changes needed
CodePudding user response:
One way to do it is to introduce some common non-generic interface IOrder and register all services as it (something similar framework does for hosted services registration and execution):
interface IOrder
{
}
interface IOrder<T> : IOrder
{
}
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrder, FurnitureOrder<Chair>>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrder, FurnitureOrder<Table>>());
And then you will be able either inject them as IEnumerable<IOrder> into your dependent class or use IServiceProvider.GetServices<IOrder>() call to resolve them.
Also note that next registration also should work:
services.AddSingleton<IOrder, FurnitureOrder<Chair>>()
services.AddSingleton<IOrder, FurnitureOrder<Table>>()
If you need generic registrations also you can automate non-generic registration with something like this (after registering all generic ones):
var serviceDescriptors = services
.Where(descriptor => descriptor.ServiceType.IsConstructedGenericType)
.Where(descriptor =>
descriptor.ServiceType.GetGenericTypeDefinition() == typeof(IOrder<>));
foreach (var sd in serviceDescriptors)
{
services.TryAddEnumerable(ServiceDescriptor.Transient(typeof(IOrder),
p => p.GetService(sd.ServiceType))); // or add desciptor creating new based on existing one
}
CodePudding user response:
Presume You mean during excecution of ConfigureServices? You could do this:
services.AddSingleton(typeof(IOrder<Chair>), f => new ChairOrder());
var listOf = new List<ServiceDescriptor>();
using var enumerator = services.GetEnumerator();
while (enumerator.MoveNext())
{
var interfaceType = enumerator.Current.ServiceType;
if (!interfaceType.IsGenericType) continue;
if (interfaceType.Name.StartsWith("iorder", System.StringComparison.OrdinalIgnoreCase))
listOf.Add(enumerator.Current);
}
var sp = services.BuildServiceProvider();
foreach(var serviceDescriptor in listOf)
{
var interfaceIWant = serviceDescriptor.ServiceType;
var objectToUse = sp.GetRequiredService(serviceDescriptor.ServiceType);
//TODO:
}
