autofac - Resolving dependency based on custom criteria -


my app relies on multiple event bus objects basic publish/subscribe notification model (http://caliburn.codeplex.com/wikipage?title=the%20event%20aggregator).

what want share instance of aggregators groups of components. component have single event bus that's shared between component a, b, , c, , event bus that's shared between d,e,f.

i want declare event busses singleton , inject them based on criteria. kinda wanna avoid subtyping event busses purposes of distinguishing resolution.

i've used google guice ioc in java allows metadata resolution parameter. aka in java allowed me equivalent this.

example:

public a([specialuseaggregator]ieventaggregator something) public b([specialuseaggregator]ieventaggregator something)  public e([anotheruseaggregator]ieventaggregator something) public f([anotheruseaggregator]ieventaggregator something) 

any suggestions?

autofac not have/use attributes registration. 1 solution use named/keyed registration feature.

so need need register 2 eventaggreator different names/keys , when registering consumer types a,b, etc can use withparameter tell autofac ieventaggreator should use given instance:

var contianerbuilder = new containerbuilder(); contianerbuilder.register(c => createandconfigurespecialeventaggregator())                         .named<ieventaggreator>("specialuseaggregator"); contianerbuilder.register(c => createandconfigureanotheruseaggregator())                         .named<ieventaggreator>("anotheruseaggregator");  contianerbuilder.registertype<a>).asself()                  .withparameter(resolvedparameter                  .fornamed<ieventaggreator>("specialuseaggregator")); contianerbuilder.registertype<b>().asself()                  .withparameter(resolvedparameter                  .fornamed<ieventaggreator>("specialuseaggregator")); contianerbuilder.registertype<c>).asself()                  .withparameter(resolvedparameter                  .fornamed<ieventaggreator>("anotheruseaggregator")); contianerbuilder.registertype<d>().asself()                  .withparameter(resolvedparameter                  .fornamed<ieventaggreator>("anotheruseaggregator")); var container = contianerbuilder.build(); 

i still use attributes can autofac because has required extension points requires more code teach autofac attribute , use correctly.

if registering types scanning cannot use use withparameter registration use metadata facility in autofac:

just create attribute hold eventaggreator key:

public class eventaggrattribute : attribute {     public string key { get; set; }      public eventaggrattribute(string key)     {         key = key;     } } 

and attribute classes:

[eventaggrattribute("specialuseaggregator")] public class aviewmodel {     public aviewmodel(ieventaggreator eventaggreator)     {     } } 

then when scanning need use withmetadatafrom register metadata:

contianerbuilder.registerassemblytypes(assembly.getexecutingassembly())             .where(t => t.name.endswith("viewmodel"))             .onpreparing(method)             .withmetadatafrom<eventaggrattribute>(); 

and need onpreparing event metadata based resolution:

private void method(preparingeventargs obj) {     // metadata["key"] coming eventaggrattribute.key     var key = obj.component.metadata["key"].tostring();     resolvedparameter resolvedparameter =          resolvedparameter.fornamed<ieventaggreator>();     obj.parameters = new list<parameter>() { resolvedparameter}; } 

here gist of working unit test.


Comments

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -