c# - Inject different implementations of an Interface to a command at runtime -


i have interface in project 2 classes implement it:

public interface iservice {    int dowork(); }  public class service1:iservice {     public int dowork()     {        return 1;     } }    public class service2:iservice {     public int dowork()     {        return 2;     } }     

i have command handler depends on iservice too:

public commandhandler1:icommandhandler<commandparameter1> {      iservice _service;        public commandhandler1(iservice service)      {           _service = service      }        public void handle()      {            //do           _service.dowork();           //do else       } }  public interface icommandhandler<tcommandparameter>                   tcommandparameter :icommandparameter {     void handle(tcommandparameter parameter); } public interface icommandparameter { } 

i want inject service1 or service2 commandhandler1 based on user selection. suppose have enum , user select value it:

public enum services {       service_one,     service_two  } 

if user selects service_one want inject service1 command handler , if selects service_two want inject service2 command handler.

i know can use named instances, , call objectfactory.getinstance<iservice>().named("service1") example, there way implement structuremap , prevent using service locator pattern?

prevent building object graphs using runtime conditions. object graphs should fixed. use runtime decisions determine path through object graph.

what seem missing here abstraction allows delegating request correct iservice implementation; let's call iservicedispatcher:

interface iservicedispatcher {     int dowork(services data); }  sealed class servicedispatcher : iservicedispatcher {     private readonly iservice service1;     private readonly iservice service2;      // note: feel free inject container here instead, long     // class part of composition root.     public servicedispatcher(iservice service1, iservice service2) {         this.service1 = service1;         this.service2 = service2;     }     public int dowork(services data) {         return this.getservice(data).dowork();     }      private iservice getservice(services data) {         switch (data) {             case services.service_one: return this.service1;             case services.service_two: return this.service2;             default: throw new invalidenumargumentexception();         }     } } 

now commandhandler1 can depend on iservicedispatcher:

public commandhandler1 : icommandhandler<commandparameter1> {      private readonly iservicedispatcher servicedispatcher;      public commandhandler1(iservicedispatcher servicedispatcher) {           this.servicedispatcher = servicedispatcher;      }         public void handle(commandparameter1 commandparameter) {            //do           this.servicedispatcher.dowork(commandparameter.service);           //do else       } } 

do note iservicedispatcher ugly name technically describes what's going on. bad idea, because interface should functionally describe want. since didn't supply domain-specific context question, best name can come ;-)


Comments

Popular posts from this blog

c# - Binding a comma separated list to a List<int> in asp.net web api -

Delphi 7 and decode UTF-8 base64 -

html - Is there any way to exclude a single element from the style? (Bootstrap) -