So Autofac allows us to select what constructor to use in case the concrete registered type has multiple candidates. It is explained here - https://autofac.readthedocs.io/en/latest/advanced/constructor-selection.html#iconstructorselector
But what if I want to use my custom constructor selector for each and every registration of which I have quite a lot (thousands across several hundreds of Autofac.Module
classes)? How can I change the default without explicitly customizing every registration?
Motivation
We have a very large .NET Framework application using MEF as IoC. We want to replace it with Autofac as a preliminary step before migrating to .NET Core.
There is Autofac.Mef, but it does not support Lazy or open generics injection, as per documentation here - https://autofac.readthedocs.io/en/latest/integration/mef.html#known-issues-gotchas
Therefore we will be migrating to Autofac proper. I have already written code that inspects the created MEF container and generates the respective Autofac registration code. But there is a problem - what if Autofac selects a different constructor than MEF? I.e. not the one attributed with [ImportingConstructor]
?
Therefore I would like to be able to customize the registration code to respect the attribute, at least for now, in order to reduce the regression risk. Sure, since the code is generated anyway, I can modify each and every registration. But I wonder if there is a better way.
There is really not a great way to do this.
A lot of the challenge is in the combination of builder syntax/callbacks used as well as the dynamic nature of things Autofac provides with concepts like registration sources.
When you register things (like RegisterType<T>()
) it adds a single callback function to the ContainerBuilder
. The overall set of chained-up registration functions gets executed at the end, during Build()
It's sort of building a middleware chain of callback-to-callback-to-callback that ends up building a complete object registration. There's no real place to "globally intercept them."
Introducing something "global" has a few some implications that aren't super-straightforward to address, which is largely why such a thing doesn't exist.
Slap a quick set of options on the ContainerBuilder
is, clearly, a really easy thing to do. It's just that the ripple effect of "change global behavior" brings a ton with it, so we haven't done it.
That said, if this is something interesting, I'd encourage you to open an issue and propose it. If you do, make sure to include the proposed design for all the little far-reaching parts like I mentioned. The team is small and designing new language features like this requires the community pitch in with the leg-work. (We have an issue for a global IPropertySelector
with a similar request, but there's no design, and there's no great way to address it.)
Addendum: While I can't iterate over solutions, I'll say this:
Based on the goal to force a particular constructor due to this MEF migration, if it was me, I'd go and...
I get that may be trivializing the issue, but migrating from MEF isn't zero work, sort of like migrating from WCF to ASP.NET Core isn't zero work.
But like I said - if it was ME, this is how I'd do it.