c# - How to register and use different implementation of same interface? -


suppose have scenario:

 using system.linq; using nunit.framework; public interface ichannel {    void write(double value); }  public class channel: ichannel {    private readonly int channelnumber;    public channel(int channelnumber) {       requires.that(channelnumber >= 0, "channelnumber >= 0");       this.channelnumber = channelnumber;    }    private int calls;    public void write(double value) {       system.console.writeline("{0} wrote on channel {1} [#{2}]", value.tostring(), channelnumber, ++calls);    } }  public interface iservice {    void do(); }  public class servicepigreek: iservice {    private readonly ichannel channel;    public servicepigreek(ichannel channel) {       requires.isnotnull(channel, "channel");       this.channel = channel;    }    public void do() {       channel.write(3.14);    } } public class serviceeuler: iservice {    private readonly ichannel channel;    public serviceeuler(ichannel channel) {       requires.isnotnull(channel, "channel");       this.channel = channel;    }    public void do() {       channel.write(2.71);    } } 

so create 2 servicepigreek channel 0 , 1 , serviceeuler channel 0:

 [testfixture] public class tests {    [test]public void without_simpleinjector() {       var ch0 = new channel(0);       var s0 = new servicepigreek(ch0);       var s1 = new servicepigreek(new channel(1));       var s2 = new serviceeuler(ch0);       s0.do();       s1.do();       s2.do();    } 

i thought of this:

    [test]public void with_simpleinjector() {       simpleinjector.container container = new simpleinjector.container();       container.registerall(new channel(0), new channel(1));       container.registerall(getallservices(container));        foreach (var service in container.getallinstances()) {          service.do();       }     }     private system.collections.generic.ienumerable getallservices(simpleinjector.container container) {       yield return new servicepigreek(container.getallinstances().elementat(1));       yield return new servicepigreek(container.getallinstances().elementat(0));       yield return new serviceeuler(container.getallinstances().elementat(0));    } 

does have better ideas on how accomplish this?

your use case not usual one, since have same implementation multiple times (as transient) in same list , need fill different implementations of ichannel interface.

i can't design, how you're registering types right makes sense. register dynamic ienumerable calls upon container upon iteration. it's nice see you're using 1 of newer features of simple injector items index using elementat o(1) operation, since returned collection implements ilist<t>.

you following make code more readable:

private ienumerable<iservice> getallservices(container container) {   var channels = container.getallinstances<ichannel>();   yield return new servicepigreek(channels.elementat(0));   yield return new servicepigreek(channels.elementat(1));   yield return new serviceeuler(channels.elementat(0)); 

}

or when iservice implementations can singleton, able following:

var container = new simpleinjector.container();  var bluechannel = new channel(0); var redchannel = new channel(1);  container.registerall<iservice>(     new servicepigreek(bluechannel),     new servicepigreek(redchannel),     new serviceeuler(bluechannel),   );  foreach (var service in container.getallinstances<iservice>()) {     service.do(); } 

instead of requesting elements index, abstract behind factory, instance:

interface ichannelprovider {     ichannel getbluechannel();     ichannel getredchannel(); } 

but, depends on scenario if works.


Comments

Popular posts from this blog

c# - Operator '==' incompatible with operand types 'Guid' and 'Guid' using DynamicExpression.ParseLambda<T, bool> -