c# - How to dynamically invoke delegates with known parameter base type? -


i trying implement own messaging system unity game. have basic version working - simplified example of follows:

// messaging class:  private dictionary<type, list<func<message, bool>>> listeners; // set other code.  public void addlistener<t>(func<message, bool> listener) t : message {     this.listeners[typeof(t)].add(listener); }  public void sendmessage<t>(t message) t : message {     foreach (func<message, bool> listener in this.listeners[typeof(t)]) {         listener(message);     } }  // other class:  private void start() {     messaging.addlistener<mymessage>(this.messagehandler); // subscribe messages of type. }  private bool messagehandler(message message) { // receive message message base type...     mymessage message2 = (mymessage)message; // ...so have cast mymessage.     // handle message. } 

this works fine. implement "magic" allow message handler called actual derived type, this:

private bool messagehandler(mymessage message) {     // handle message. } 

this mean message handling code across thousands of scripts not need bother casting message object correct derived type - of type. far more convenient. feel possible achieve somehow using generics, delegates, expression trees, covariance and/or contravariance, i'm not getting it!

i've been trying lot of different things, , feel getting close, can't there. these 2 partial solutions i've been able come with:

// messaging class:  private dictionary<type, list<delegate>> listeners; // delegate instead of func<message, bool>.  public void addlistener<t>(func<t, bool> listener) t : message { // func<t, bool> instead of func<message, bool>.     this.listeners[typeof(t)].add(listener); }  public void sendmessage<t>(t message) t : message {     foreach (delegate listener in this.listeners[typeof(t)]) {         listener.method.invoke(method.target, new object[] { message }); // partial solution 1.         ((func<t, bool>)listener)(message); // partial solution 2.     } } 

partial solution 1 works fine, uses reflection, isn't option considering performance - game, , messaging system used lot. partial solution 2 works, long t generic parameter available. messaging system have queue of message objects process, , t not available there.

is there way achieve this? appreciate offer!

one final thing note using unity, uses mono - .net 4 not option, , far know rules out using "dynamic".

if understood question correctly, want have common way of storing , invoking message handlers while providing specific message type each handler.

one way use base-typed inteface handler , generic-typed implementation:

interface imessagehandler {     bool processmessage(message m); }  class messagehandler<t>: imessagehandler t:message {     func<t, bool> handlerdelegate;      public messagehandler(func<t, bool> handlerdelegate)     {         this.handlerdelegate = handlerdelegate;      }      public bool processmessage(message m)     {         handlerdelegate((t)m);       } } 

your handler dictionary should hold imessagehandler value, , in addlistener method create messagehandler , add handler dictionary. this:

private dictionary<type, imessagehandler> listeners;  public void addlistener<t>(func<t, bool> listener) t : message  {      this.listeners[typeof(t)].add(new messagehandler<t>(listener)); }  public void sendmessage(message message)  {     foreach (imessagehandler listener in this.listeners[message.gettype()])      {        listener.processmessage(message);     } } 

that way can call sendmessage without generic parameter , typed argument in actual handler method.


Comments

Popular posts from this blog

plot - Remove Objects from Legend When You Have Also Used Fit, Matlab -

java - Why does my date parsing return a weird date? -

Need help in packaging app using TideSDK on Windows -