Open adj123 opened 2 years ago
Hey @adj123! 👋🏻
I think this might be solvable by using the new "keyed services" in .NET 8. I might introduce an overload that takes a key when decorating, which will let you refer to that specific decorator when resolving using the key.
Do you think this could work?
Hey, I haven't had a chance to play around with these yet, but from their description it does sound like this approach would work well as a solution to this problem!
@khellang do you have some estimation when this keyed services feature will be available? I'm eagerly waiting for it
Alternatively, after looking at the implementation further, I've realised we actually already do register a handle to the decorated service, we just don't expose it - the DecoratedType
service descriptor. So a clean way to do this would be to add a wrapper like
public sealed record DecoratedService<TService>(Type Type);
public static TService GetRequiredService<TService>(this IServiceProvider provider, DecoratedService<TService> serviceType) =>
(TService)provider.GetRequiredService(serviceType.Type);
and new overloads like
public static IServiceCollection Decorate<TService, TDecorator>(this IServiceCollection services, out DecoratedService<TService> decorated)
{
... decorate ...
DecoratedType decoratedType = ...;
decorated = new(decoratedType);
}
and then we can call it with something like (to use my earlier example):
services.Decorate<IMyExternalService, CachingLayerOverMyExternalService>(out var cachingLayer);
services.AddHostedService(sp => sp.GetRequiredService(cachingLayer));
services.Decorate<IMyExternalService, SomethingElseDecoratingMyExternalService>();
How does that sound?
Hi, I have possibly a slightly unusual case where I have some class which needs to be decorated twice, with the inner one registered as a hosted service:
The
AddHostedService
line doesn't work because by the time the function executes,IMyExternalService
is already decorated withSomethingElseDecoratingMyExternalService
. My only workaround at the moment is to publicly expose the underlyingIMyExternalService
in this decorator, but this is a hack - it's not part of the decorator's functionality, it's only there to facilitate the DI mechanism which happens to be used to compose all the classes.I need some handle to be able to reference that inner decorator somehow for my
AddHostedService
call - eg. perhaps ifDecorate
also registered a transient service pointer to each decorated type, like if I could do:I imagine the general problem here isn't limited to hosted services and this solution would help for cases when the decorator implements arbitrary multiple interfaces which it also needs to be registered against.