Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You could also use some sort of IoC framework, like Spring.NET, to inject the dictionary. This way, if you get a new message type, you don't have to recompile this central hub - just change a config file. <hr/> The long awaited example:</p> <p>Create a new console app, named Example, and add this:</p> <pre><code>using System; using System.Collections.Generic; using Spring.Context.Support; namespace Example { internal class Program { private static void Main(string[] args) { MessageBroker broker = (MessageBroker) ContextRegistry.GetContext()["messageBroker"]; broker.Dispatch(null, new Type1EventArgs()); broker.Dispatch(null, new Type2EventArgs()); broker.Dispatch(null, new EventArgs()); } } public class MessageBroker { private Dictionary&lt;Type, object&gt; handlers; public Dictionary&lt;Type, object&gt; Handlers { get { return handlers; } set { handlers = value; } } public void Dispatch&lt;T&gt;(object sender, T e) where T : EventArgs { object entry; if (Handlers.TryGetValue(e.GetType(), out entry)) { MessageHandler&lt;T&gt; handler = entry as MessageHandler&lt;T&gt;; if (handler != null) { handler.HandleMessage(sender, e); } else { //I'd log an error here Console.WriteLine("The handler defined for event type '" + e.GetType().Name + "' doesn't implement the correct interface!"); } } else { //I'd log a warning here Console.WriteLine("No handler defined for event type: " + e.GetType().Name); } } } public interface MessageHandler&lt;T&gt; where T : EventArgs { void HandleMessage(object sender, T message); } public class Type1MessageHandler : MessageHandler&lt;Type1EventArgs&gt; { public void HandleMessage(object sender, Type1EventArgs args) { Console.WriteLine("Type 1, " + args.ToString()); } } public class Type2MessageHandler : MessageHandler&lt;Type2EventArgs&gt; { public void HandleMessage(object sender, Type2EventArgs args) { Console.WriteLine("Type 2, " + args.ToString()); } } public class Type1EventArgs : EventArgs {} public class Type2EventArgs : EventArgs {} } </code></pre> <p>And an app.config file:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt; &lt;configuration&gt; &lt;configSections&gt; &lt;sectionGroup name="spring"&gt; &lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&gt; &lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/&gt; &lt;/sectionGroup&gt; &lt;/configSections&gt; &lt;spring&gt; &lt;context&gt; &lt;resource uri="config://spring/objects"/&gt; &lt;/context&gt; &lt;objects xmlns="http://www.springframework.net"&gt; &lt;object id="messageBroker" type="Example.MessageBroker, Example"&gt; &lt;property name="handlers"&gt; &lt;dictionary key-type="System.Type" value-type="object"&gt; &lt;entry key="Example.Type1EventArgs, Example" value-ref="type1Handler"/&gt; &lt;entry key="Example.Type2EventArgs, Example" value-ref="type2Handler"/&gt; &lt;/dictionary&gt; &lt;/property&gt; &lt;/object&gt; &lt;object id="type1Handler" type="Example.Type1MessageHandler, Example"/&gt; &lt;object id="type2Handler" type="Example.Type2MessageHandler, Example"/&gt; &lt;/objects&gt; &lt;/spring&gt; &lt;/configuration&gt; </code></pre> <p>Output:</p> <pre> Type 1, Example.Type1EventArgs Type 2, Example.Type2EventArgs No handler defined for event type: EventArgs </pre> <p>As you can see, <code>MessageBroker</code> doesn't know about any of the handlers, and the handlers don't know about <code>MessageBroker</code>. All of the mapping is done in the app.config file, so that if you need to handle a new event type, you can add it in the config file. This is especially nice if other teams are defining event types and handlers - they can just compile their stuff in a dll, you drop it into your deployment and simply add a mapping.</p> <p>The Dictionary has values of type object instead of <code>MessageHandler&lt;></code> because the actual handlers can't be cast to <code>MessageHandler&lt;EventArgs></code>, so I had to hack around that a bit. I think the solution is still clean, and it handles mapping errors well. Note that you'll also need to reference Spring.Core.dll in this project. You can find the libraries <a href="http://downloads.sourceforge.net/springnet/Spring.NET-1.1.2.zip?modtime=1210044370&amp;big_mirror=0" rel="nofollow noreferrer">here</a>, and the documentation <a href="http://springframework.net/docs/1.1.2/reference/html/index.html" rel="nofollow noreferrer">here</a>. The <a href="http://springframework.net/docs/1.1.2/reference/html/objects.html#objects-dependencies" rel="nofollow noreferrer">dependency injection chapter</a> is relevant to this. Also note, there is no reason you need to use Spring.NET for this - the important idea here is dependency injection. Somehow, something is going to need to tell the broker to send messages of type a to x, and using an IoC container for dependency injection is a good way to have the broker not know about x, and vice versa.</p> <p>Some other SO question related to IoC and DI:</p> <ul> <li><a href="https://stackoverflow.com/questions/139299/difference-between-dependency-injection-di-inversion-of-control-ioc">Difference between Dependency Injection (DI) &amp; Inversion of Control (IOC)</a></li> <li><a href="https://stackoverflow.com/questions/21288/which-cnet-dependency-injection-frameworks-are-worth-looking-into">Which C#/.net Dependency Injection frameworks are worth looking into?</a></li> <li><a href="https://stackoverflow.com/questions/148908/which-dependency-injection-tool-should-i-use">Which Dependency Injection Tool Should I Use?</a></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload