Note that there are some explanatory texts on larger screens.

plurals
  1. POStrongly typed way of storing type references
    text
    copied!<p>I need to store a collection of types.</p> <p>All types implement the same interface <code>IHandler&lt;T&gt;</code>, where <code>T</code> is a parameter of the parent class.</p> <p>At runtime, I enumerate the list of handlers and process a message. Each handler is created by a builder (just uses StructureMap internally). The builder exposes a method like:</p> <pre><code>static void DoSomething&lt;T&gt;(Action&lt;T&gt; action) { } </code></pre> <p>Of course, I only have a <code>Type</code> so can't use the above.</p> <p>I've got round this by also passing the underlying interface as the generic parameter and the concrete type as a parameter:</p> <pre><code>DoSomething&lt;IHandler&lt;T&gt;&gt;(handlerType, h =&gt; { h.Handle(message); }); </code></pre> <p>Then inside <code>DoSomething</code> I can get an instance of <code>handlerType</code> but cast it as <code>IHandler&lt;T&gt;</code>.</p> <p>Just wondered if there was a better/cleaner way.</p> <h3>Update</h3> <p>In response to some of the comments.</p> <p>The collection is an <code>ICollection&lt;Type&gt;</code>, not instances. The message handlers are created on demand, on different threads, for each batch of messages, so creating the handlers in advance, or using <code>Lazy&lt;T&gt;</code>, was not an option.</p> <p>Essentially I am trying to abstract away some direct references to StructureMap. Specifically, <code>DoSomething&lt;T&gt;</code> actually creates the handler using a nested container, before executing the action (it's <code>Handle</code> method).</p> <h3>Update 2 (solution)</h3> <p>I realized that I could handle (no pun intended) this better by storing a collection of <code>Action&lt;T&gt;</code> and creating the handlers using a factory. Here's a simple example:</p> <pre><code>public class SimpleProcessor&lt;T&gt; where T : IMessage { ICollection&lt;Action&lt;T&gt;&gt; handlers; T message; public SimpleProcessor(T message) { this.handlers = new List&lt;Action&lt;T&gt;&gt;(); this.message = message; } public void AddHandler(Action&lt;T&gt; handler) { handlers.Add(handler); } public void Process() { foreach (var handler in handlers) { handler(message); } } } </code></pre> <p>Usage:</p> <pre><code>var testMessage = new TestMessage { Message = "Foo" }; var simpleProcessor = new SimpleProcessor&lt;TestMessage&gt;(testMessage); simpleProcessor.AddHandler(m =&gt; DoSomething&lt;TestMessageHandler&gt;(h =&gt; h.Handle(m))); simpleProcessor.Process(); </code></pre> <p>I'm more or less happy with this solution.</p>
 

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