Is there a way to take an existing Autofac Module
, Container
or ContainerBuilder
and use it to generate an equivalent json file that can be loaded via configuration extensions?
For some background, we have a large code base with hundreds of registrations and dozens of configurations, each with its own json config file. Managing these files after they were deployed became a nightmare so we've since moved everything to a single autofac module with a few parameters exposed to support the different configuration combinations.
This is much more manageable, but occasionally our users need to "tweak" one of the registrations, which we can't do anymore without providing a new build.
My first thought was to give them a tool that would build up the container in code and then export its registrations to a config file that these specific users could leverage instead. I started by just trying to find something on the autofac side to decorate, so I could "intercept" registrations:
public sealed class AutofacGenerator : IModuleRegistrar
...
public IModuleRegistrar RegisterModule(IModule module)
{
_modules.Add(module);
_decorated.RegisterModule(module);
return this;
}
// extension method `ToJson` not shown
public IEnumerable<string> Generate() => _modules.Select(module => module.ToJson());
Then in my top level module I add this:
public class MyAutofacModule: Module
...
protected override void Load(ContainerBuilder builder)
{
Generate(builder);
}
public IEnumerable<string> Generate(ContainerBuilder builder)
{
var generator = new AutofacGenerator(decorated: builder);
generator.RegisterModule(new MySubModule1());
generator.RegisterModule(new MySubModule2());
...
return generator.Generate();
}
And use it like this:
var myJsonifiedModules = new MyAutofacModule().Generate()
// save these strings to a file, not shown...
Obviously this has several issues. This only exports modules, which is okay for my purposes but ideally I'd intercept all registrations. I was hoping to decorate ContainerBuilder
and pass it in from the top, but it's sealed without virtual methods.
Also I'm not really decorating anything, but since Autofac's extension methods creates and uses its own concrete ModuleRegistrar
this is the best I can do.
There's no point in implementing their interface besides making my intent clear and keeping the method signature the same to make it easier to swap in...
The above issues mean I'm stuck having to modify my top level module (or any module I want to export) to use AutofacGenerator
.
Perhaps decorating is the wrong approach. I also tried just using the Container.ComponentRegistry.Registrations
and Container.ComponentRegistry.Sources
directly but quickly got overwhelmed with how to translate those into json. Also, there doesn't seem to be a way to back out what modules were used, so my generated file would be one flat list of component registrations only.
I feel like I can't be the only one where the ability to export configs would be useful. Are there existing approaches to this problem I can leverage?