c# - conditional component registration in autofac -
is possible register component conditionally on other component's state? like:
containerbuilder.registerconditionally<t>( func<icomponentcontext, bool>, func<icomponentcontext, t>);
i've found prior v2 of autofac 1 use "register().onlyif()
" construction seemed 1 i'm looking for. such feature conditionally override default registration.
class commonregistrations { public virtual void register(containderbuilder builder) { builder.register(ctx => loadsettings()).as<isettings>().singleinstance(); builder.registertype<defaultfoo>().as<ifoo>(); } } class specificregistrations : commonregistrations { public virtual void register(containerbuilder builder) { base.register(builder); builder.conditionalyregister( ctx => ctx.resolve<isettings>().reallyusespecificfoo, ctx => new specificfoo()).as<ifoo>(); } } ... var builder = new containerbuilder(); var registrations = new specificregistrations(); registrations.register(builder); var container = builder.build(); ifoo foo = container.resolve<ifoo>();
the foo according isettings.reallyusespecificfoo
either instance of defaultfoo
or instance of specificfoo
.
thank you.
there no way perform conditional registration @ container level based on container contents. trouble need resolve in container in order determine gets registered in container, technically affect whether wanted register thing in first place. chicken/egg circular dependency problem.
you can, however, register things conditionally nested lifetime scopes. integration points (like asp.net) resolve out of nested lifetime scopes (like http-request-length lifetime scope). can register things on fly nested lifetime scopes , might solve problem.
var builder = new containerbuilder(); builder.register(ctx => loadsettings()).as<isettings>().singleinstance(); builder.registertype<defaultfoo>().as<ifoo>(); var container = builder.build(); var settings = container.resolve<isettings>(); using(var scope = container.beginlifetimescope(b => { if(settings.reallyusespecificfoo) { b.registertype<specificfoo>().as<ifoo>(); } }) { // resolve things nested lifetime scope - // use overrides. specificfoo if // configuration setting true. var foo = scope.resolve<ifoo>(); }
another option have make registration lambda. might make registration more complex it's option consider.
var builder = new containerbuilder(); builder.register(ctx => { var settings = ctx.resolve<isettings>(); if(settings.reallyusespecificfoo) { return new specificfoo(); } return new defaultfoo(); }).as<ifoo>();
if manual construction there isn't appealing, pass through autofac, too.
var builder = new containerbuilder(); // register ifoo types - not "as<ifoo>" builder.registertype<defaultfoo>(); builder.registertype<specificfoo>(); // in lambda use resolve<t> instances. builder.register(ctx => { var settings = ctx.resolve<isettings>(); if(settings.reallyusespecificfoo) { return ctx.resolve<specificfoo>(); } return ctx.resolve<defaultfoo>(); }).as<ifoo>();
yet option update existing container after being built. in case, avoid chicken/egg scenario building container, using it, , changing registrations after fact.
var builder = new containerbuilder(); builder.register(ctx => loadsettings()).as<isettings>().singleinstance(); builder.registertype<defaultfoo>().as<ifoo>(); var container = builder.build(); var settings = container.resolve<isettings>(); if(settings.reallyusespecificfoo) { var updater = new containerbuilder(); updater.registertype<specificfoo>().as<ifoo>(); updater.update(container); }
finally, might consider xml configuration. given registration dependent on sort of configuration setting, might consider using autofac's xml configuration support. way, instead of trying resolve out of un-built container conditionally register else, specify right thing register using xml configuration , register correct thing first time.
Comments
Post a Comment