c# - SimpleInjector HowTo Register multiple Open Generic Interfaces for a Single Generic Implementation -


i'm trying started simpleinjector ioc container , i'm pretty happy it. right i'm stuck on problem can't solve. searched on , in documentation, seems not answered yet. i've seen the howto doc simpleinjector doesn't cover open generic interfaces.

i have 2 generic interfaces these:

public interface ieventpublisher<tevent> {    void publish(tevent event); } public interface ieventsubscriber<tevent> {     void subscribe(action<tevent> callback); } 

and 1 open generic implementation two:

class eventmediator<t> : ieventpublisher<t>, ieventsubscriber<t> {     list<action<t>> subscriptions = new list<action<t>>();      public void publish(t event)     {         foreach (var subscription in this.subscriptions)             subscription.invoke(event);     }      public void subscribe(action<t> callback)     {         this.subscriptions.add(callback);     } } 

in application i'm setting simpleinjector this:

this.container = new simpleinjector.container(); this.container.registeropengeneric(typeof(ieventpublisher<>), typeof(eventmediator<>), lifestyle.singleton); this.container.registeropengeneric(typeof(ieventsubscriber<>), typeof(eventmediator<>), lifestyle.singleton); this.container.verify(); 

what i'm trying archive is: i'd same instance when asking ieventpublisher or ieventsubscriber. , furthermore instance shall singleton t.

i've tested these lines:

class dummyevent {}  var p = this.container.getinstance<ieventpublisher<dummyevent>>(); var s = this.container.getinstance<ieventsubscriber<dummyevent>>(); var aresame = (object.referenceequals(p,s)); 

unfortunatly p , s don't refer same instance. happens know solution problem?

there solutions this, here's one: create separate implementations ieventpublisher<t> , ieventsubscriber<t> , let them delegate eventmediator<t>. instance these implementations:

public class eventpublisher<tevent> : ieventpublisher<tevent> {     private readonly eventmediator<tevent> mediator;     public eventpublisher(eventmediator<tevent> mediator) {         this.mediator = mediator;     }      public void publish(tevent event) {         this.mediator.publish(event);     } }  public class eventsubscriber<tevent> : ieventsubscriber<tevent> {     private readonly eventmediator<tevent> mediator;     public eventsubscriber(eventmediator<tevent> mediator) {         this.mediator = mediator;     }      public void subscribe(action<tevent> callback) {         this.mediator.subscribe(callback);     } } 

now make registrations follows:

container.registersingleopengeneric(typeof(eventmediator<>), typeof(eventmediator<>)); container.registersingleopengeneric(typeof(ieventpublisher<>), typeof(eventpublisher<>)); container.registersingleopengeneric(typeof(ieventsubscriber<>), typeof(eventsubscriber<>)); 

now both eventpublisher<dummyevent> , eventsubscriber<dummyevent> point @ same eventmediator<dummyevent> instance.

another way achieve without type make use of resolveunregisteredtype event (which registeropengeneric extension method uses under covers). configuration this:

container.registersingleopengeneric(typeof(eventmediator<>), typeof(eventmediator<>));  container.resolveunregisteredtype += (s, e) => {     if (e.unregisteredservicetype.isgenerictype)     {         var def = e.unregisteredservicetype.getgenerictypedefinition();          if (def == typeof(ieventpublisher<>) || def == typeof(ieventsubscriber<>))         {             var mediatortype = typeof(eventmediator<>)                 .makegenerictype(e.unregisteredservicetype.getgenericarguments()[0]);             var producer = container.getregistration(mediatortype, true);             e.register(producer.registration);         }     } }; 

you extract code more general extension method. way registration this:

container.registersingleopengeneric(typeof(eventmediator<>), typeof(eventmediator<>)); container.forwardopengenericto(typeof(ieventpublisher<>), typeof(eventmediator<>)); container.forwardopengenericto(typeof(ieventsubscriber<>), typeof(eventmediator<>)); 

the extension method this:

public static void forwardopengenericto(this container container,     type opengenericservicetype, type opengenericservicetypetoforwardto) {     container.resolveunregisteredtype += (s, e) =>     {         var type = e.unregisteredservicetype;         if (type.isgenerictype)         {             if (type.getgenerictypedefinition() == opengenericservicetype)             {                 var forwardtotype = opengenericservicetypetoforwardto.makegenerictype(                     type.getgenericarguments());                 var producer = container.getregistration(forwardtotype, true);                 e.register(producer.registration);             }         }     }; } 

Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -