Search code examples
c#decoratorautofac

Autofac 6 - register decorators conditional on the availability of another service


Before v6, if I wanted to register a decorator depending on the availability of another service - not depending on other decorators applied -, I could do something like:

builder.RegisterType<ApiClientMetricsDecorator>()
       .As(new DecoratorService(typeof(IApiClient)))
       .OnlyIf(b => b.IsRegistered(new TypedService(typeof(IApiCallMetricsReceiver))));

This does not work anymore. The decorator is not being applied. The reason for this seems to be that internally now the new v6 middleware mechanism is used for decorators.

The existing .RegisterDecorator overloads allow only to pass in a Func<IDecoratorContext, bool>, but IDecoratorContext does not let me check whether a service has been registered, it's only for inspecting the decorator chain and the target instance.

Unfortunately, I cannot just create another local extension method by replicating the source of RegisterDecorator and adjusting as I need because it turns out that the type DecoratorMiddleware is internal.

So what is the way to achieve what I need with v6? Currently the only way I can think of would be to register the decorator always and do another registration:

builder.RegisterType<NullApiCallMetricsReceiver>()
       .As<IApiCallMetricsReceiver>()
       .IfNotRegistered(typeof(IApiCallMetricsReceiver));

But this would be a very ugly workaround because I would completely unnecessarily add a decorator that does nothing.

If it's relevant, the reason why I need this is because the above registration of the decorator resides in a module in an assembly that is being used by different projects and only in some of these, metrics are relevant and so they register a type providing IApiCallMetricsReceiver.

I got the same pattern multiple times in my code base.

Any help would be greatly appreciated, this is currently keeping me from upgrading to Autofac v6, and I hate being not up-to-date with core libraries like Autofac.


Solution

  • This is a really good question. Unfortunately, I don't think I'm going to have a satisfactory answer:

    In Autofac v6... you can't really do what you want. Right now. For the reasons you mentioned - it's not just about services now, it's about managing the resolution pipeline.

    But! I have filed an issue on your behalf to get OnlyIf support for decorators in place. We just recently implemented some internals changes that would allow this to happen, so it's pretty good timing.

    I don't have a deadline/ETA on when this will be delivered, but it's on the radar. You can subscribe to the issue to follow along if you like.