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
Post a Comment