﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>JoeMoe commented on Challenge: calling generics without the generic type</title><description>Ayende,
  
  
Can you post a complete working example of your solution? With mapping messages to handlers etc. 
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment49</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment49</guid><pubDate>Thu, 17 Apr 2008 14:04:30 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Alex: off to see some wizard I guess
  
Bryan: That's right, but whenever I use a concrete type for a reference, I'm afraid some blogger like Ayende will jump out of an open browser window and drag me to the daily WTF ;-) I'd rather have a different name/signature. 
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment48</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment48</guid><pubDate>Tue, 15 Apr 2008 16:06:43 GMT</pubDate></item><item><title>Alex Simkin commented on Challenge: calling generics without the generic type</title><description>Where is Ayende?
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment47</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment47</guid><pubDate>Tue, 15 Apr 2008 15:51:21 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>P.S. When using a concrete reference, just the strongly-typed API is exposed. *Only* when using interfaces do you lose type safety, and even then it's not lost, just 1 step away :-)
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment46</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment46</guid><pubDate>Tue, 15 Apr 2008 15:31:48 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>You are correct. The option is in the hands of the user when using an interface reference. The untyped method simply calls the typed method with a cast, so it still buys a single point of typing transition. But it does degrade the API a little.
  
  
I use this pattern mostly for writing concrete object hierarchies deriving from a base implementation of the generic interface, something like:
  
  
public abstract class ValidationRule&lt;T&gt; : IValidationRule&lt;T&gt;
  
{
  
...
  
}
  
  
public class EmailRule : ValidationRule&lt;string&gt;
  
{
  
...
  
}
  
  
Now, I can easily reason about the objects comprising the framework, from any perspective.
  
  
This pattern makes less sense in the message handler example, with only 1 concrete type.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment45</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment45</guid><pubDate>Tue, 15 Apr 2008 15:29:20 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Another point: When you define an f(X) for every f(T) where T: X, you'll lose type safety. Same name, same signature except for the super type: that will always compile, even if it becomes invalid due to some other changes. The generic method becomes a mere hint via intellisense.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment44</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment44</guid><pubDate>Tue, 15 Apr 2008 09:05:53 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Bryan,
  
  
the guy who does the cursing might be myself - I'm not always designing libraries for other people. In that case, I (or a coworker) can add the untyped stuff when I need it and not clutter everything with duplicate stuff just in case. Thus the reference to YAGNI. In other cases, I might choose to use _only_ untyped interfaces, because generics somtimes only add complexity. In a situation like this here, I might end up having only generic interfaces for the beauty and clarity of it, but avoid handling different messages in one type, but chances are I'd rather avoid the generics completely, since the handle method is likely to be invoked in generic handler loops only. I'll stick with case-by-case decisions.
  
  
BTW, instead of cursing, one could just write their generic wrappers (like my DoDispatch method) and call them using a more general method, like that one:
  
      var action = ReflectionUtility.MakeGenericWrapper ((AbstractMessage msg) =&gt; Dispatch (msg));
  
      action (new AbstractMessage ());
  
      action (new ConcreteMessage ());
  
  
Granted, this might be more magic that you'd want to expose the users of your types to, but it can be done :-)
  
  
In this very case I'd go with generics, because when I'm asked, out of context, how to make generics fly, getting rid of those generics does not seem like much of an answer. In real life, it may well be.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment43</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment43</guid><pubDate>Mon, 14 Apr 2008 23:49:07 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>Stefan,
  
  
I suggested the name change to bring the method in line with the existing public API. I was not commenting on stylistic choice - "Do*" is a well known naming convention for "actual-work" methods.
  
  
I agree that this challenge doesn't make sense in the context of multiple implementations - we at least need some mapping of message type to handler type, otherwise how do we know what to instantiate?
  
  
As for non-generic interfaces: I consider them a necessary aspect of implementing generic classes. Someone somewhere will curse you because they can't act upon your object in an abstract manner which is meaningful.
  
  
I like to think of Eric Lippert's "intent vs mechanism" dichotomy: an untyped interface declares an intent of untyped usage; the same intent cannot otherwise be expressed sans imperative code.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment42</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment42</guid><pubDate>Mon, 14 Apr 2008 21:47:59 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Bryan,
  
  
I'm not going to argue about naming, just like I cannot argue about methods being static, caches being thread-safe or what have you. There's just no information to base those decisions on. I named the thing DoDispatch to have separate names and make the sample more readable, that's all. It's just a quiz, but it seems to be more about reading Ayende's thoughts than about solving the actual problem. Maybe that's what he wanted:
  
  
public void Dispatch(AbstractMessage msg, Type handlerType)
  
{
  
	IMessageHandler&amp;lt;msg.GetType()&amp;gt; handler =(IMessageHandler&amp;lt;msg.GetType()&amp;gt;) Activator.Create (handlerType);
  
	handler.Handle(msg);
  
}
  
  
Because instantiating a handler that implements IMessageHandler&amp;lt;IMsg1&amp;gt; and &amp;lt;IMsg2&amp;gt; via new MyHandler&amp;lt;T&amp;gt; makes little sense to me. That's why I initially recommended to just call Handle&amp;lt;AbstractMessage&amp;gt; and be done with it.
  
  
Anyway, the trick is using Expression.Compile for LCG, the rest is beyond this challenge. You could even build it into a reflection utility class that knows nothing about IMessageHandler, and pass DoDispatch as a parameter. 
  
  
Providing a non-generic interface should be a case by case decision. Once, because YAGNI, and then because we just showed that it's not that hard to work around it if it's missing. Implementing manual dispatching like you did for the non-generic Handle method is tedious, and error-prone if you never really use it. Even if you're into TDD you can easily miss a case. It's just not DRY. (now I'm running out of impressive acronyms...)
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment41</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment41</guid><pubDate>Mon, 14 Apr 2008 19:57:38 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>Stefan,
  
  
For the problem stated, we have six of one, a half dozen of the other. I would suggest you rename "DoDispatch" to "Dispatch" and make it public, allowing compile-time consumers to bypass the reflection.
  
  
The subtle difference is that your solution is scoped to the method, mine to the class. General instantiation of MessageHandler&lt;T&gt; offers more reuse than the single instance in "Dispatch".
  
  
I also prefer to implement any generic class with an untyped interface (IMessageHandler&lt;T&gt; : IMessageHandler). Without, you eventually get into situations where you simply lack the correct nouns!
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment40</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment40</guid><pubDate>Mon, 14 Apr 2008 19:27:52 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Bryan,
  
  
yes, actually I'm not arguing with your solution, but with Ayendes statements about it. I _still_ maintain, that without multiple implementations of IMessageHandler&lt;T&gt;, you usually don't need any of this. With it (and his intitial question does not show this), you can still go down the generic road like I described, so why code all that non-generic interface stuff and dispatch the call manually?
  
  
    public static void Dispatch (AbstractMessage msg)
  
    {
  
      Type T = msg.GetType ();
  
      Action&lt;AbstractMessage&gt; action;
  
  
      if (! _cache.TryGetValue (T, out action) )
  
      {
  
        MethodInfo doDispatch = typeof (Program).GetMethod ("DoDispatch", BindingFlags.NonPublic | BindingFlags.Static); // cache this 
  
        doDispatch = doDispatch.MakeGenericMethod (T);
  
  
        // (AbstractMsg m) =&gt; doDispatch&lt;T&gt; ((T) m)
  
        var msgParam = Expression.Parameter (typeof (AbstractMessage), "msg");
  
        action = Expression.Lambda&lt;Action&lt;AbstractMessage&gt;&gt; (
  
                Expression.Call (doDispatch, Expression.Convert(msgParam, T)),
  
                msgParam)
  
            .Compile();
  
        _cache.Add (T, action);
  
      }
  
  
      action (msg);
  
    }
  
  
    private static void DoDispatch&lt;T&gt; (T msg) where T : AbstractMessage
  
    {
  
      IMessageHandler&lt;T&gt; handler = new MyHandler&lt;T&gt;();
  
      handler.Handle(msg);
  
    }
  
  
that's it, so why bother with anything less?
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment39</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment39</guid><pubDate>Mon, 14 Apr 2008 18:43:29 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>Stefan Wenig,
  
  
You are right, my solution as coded does not facilitate multiple implementations of IMessageHandler&lt;T&gt;.
  
  
I was constructing a type hierarchy which allows both generic and non-generic references to the same object. Classes themselves are fully-typed; the only thing which changes is your perspective (the type of your reference).
  
  
That said, I may have misunderstood the intent of the class. I was pumping a concrete type through something which has a generic parameter, giving compile-time access to an otherwise unknown type.
  
  
Multiple interfaces generally means explicit implementation and multiple pathways. Rather than handling any case, you handle very specific cases:
  
  
public class Handles1And2 : IMessageHandler&lt;Msg1&gt;, IMessageHandler&lt;Msg2&gt;
  
{
  
void IMessageHandler&lt;Msg1&gt;.Handle(Msg1 msg)
  
{
  
HandleMsg1(msg);
  
}
  
  
void IMessageHandler&lt;Msg2&gt;.Handle(Msg2 msg)
  
{
  
HandleMsg2(msg);
  
}
  
  
void IMessageHandler.Handle(AbstractMessage msg)
  
{
  
  if(msg is Msg1)
  
  {
  
    HandleMsg1((Msg1) msg);
  
  }
  
  else if(msg is Msg2)
  
  {
  
    HandleMsg2((Msg2) msg);
  
  }
  
  else
  
  {
  
    // Argument error
  
  }
  
}
  
  
public void HandleMsg1(Msg1 msg)
  
{
  
...
  
}
  
  
public void HandleMsg2(Msg2 msg)
  
{
  
...
  
}
  
}
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment38</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment38</guid><pubDate>Mon, 14 Apr 2008 15:49:17 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Refesh,
  
  
That code creates a delegate for this method:
  
string GetSecurityKeyPropertyInternal&lt;TEntity&gt;()
  
  
This is only possible because the generic type does not affect the signature. That's not the case for Handle(T msg), you cannot create an Action&lt;AbstractMessage&gt; for a method that takes a concrete message type, it works only the other way around (contravariance for input parameters)
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment37</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment37</guid><pubDate>Mon, 14 Apr 2008 11:08:47 GMT</pubDate></item><item><title>Reshef Mann commented on Challenge: calling generics without the generic type</title><description>Stefan,
  
U can take a look at the method 'GetSecurityKeyProperty' in 
  
  
https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/rhino-security/Rhino.Security/Security.cs
  
  
to see how u can avoid LCG.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment36</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment36</guid><pubDate>Mon, 14 Apr 2008 10:21:59 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>I just noticed that your blog configuration even swallows non-breaking spaces in comments. That's a pain for posting source code.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment35</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment35</guid><pubDate>Mon, 14 Apr 2008 06:53:45 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Ayende,
  
  
&gt; A single class may implement more than a single IMessageHandler&lt;T&gt; 
  
  
OK, now that's a design where just doing
  
  handler = new MyHandler&lt;AbstractMessage&gt;();
  
as I initially suggested would not work. I thought it's just
  
  MyHandler&lt;T&gt; : IMessageHandler&lt;T&gt;
  
  
But, given 
  
  MyHandler : IMessageHandler&lt;Msg1&gt;, IMessageHandler&lt;Msg2&gt;
  
I don't see how Bryan's solution would work:
  
  public class MessageHandler&lt;T&gt; : IMessageHandler&lt;T&gt; {
  
    void IMessageHandler.Handle(AbstractMessage msg) {
  
      return Handle((T) msg);
  
  }}
  
  
When you're implementing multiple IMessageHandler&lt;T&gt;, there's no T to cast the msg to, which puts us on square one. When you're not, I still maintain you can just call it by passing AbstractMessage (or whatever that class's T is constrained to), unless the implementation does something unlikely.
  
  
That's why I suggested coding the entire Dispatch method as a generic Dispatch&lt;T&gt; method and use Expression/Compile only to invoke that method with the correct T.
  
  
Mind to explain what I'm missing?
  
  
I'd still like to see your solution that involves no LCG at all, btw.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment34</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment34</guid><pubDate>Mon, 14 Apr 2008 06:47:05 GMT</pubDate></item><item><title>Ayende Rahien commented on Challenge: calling generics without the generic type</title><description>Bryan Watts,
  
Very good. I used a delegate and a manual dictionary, but that is my approach.
  
I like yours beter
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment33</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment33</guid><pubDate>Mon, 14 Apr 2008 03:10:31 GMT</pubDate></item><item><title>Ayende Rahien commented on Challenge: calling generics without the generic type</title><description>Romain Verdier,
  
You have the right approach, but LCG is not required.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment32</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment32</guid><pubDate>Mon, 14 Apr 2008 03:07:39 GMT</pubDate></item><item><title>Ayende Rahien commented on Challenge: calling generics without the generic type</title><description>Frans,
  
A single class may implement more than a single IMessageHandler&lt;T&gt;
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment31</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment31</guid><pubDate>Mon, 14 Apr 2008 03:04:39 GMT</pubDate></item><item><title>Maruis Marais commented on Challenge: calling generics without the generic type</title><description>Instead of having the generic declaration on the interface, I'd rather have it on the method:
  
  
  public interface IMessageHandler
  
  {
  
    void Handle&lt;T&gt;(T msg) where T : AbstractMessage;
  
  }
  
  
That means that the concrete implementation could look like this:
  
  
  internal class MyHandler : IMessageHandler
  
  {
  
    public void Handle&lt;T&gt;(T msg) where T : AbstractMessage
  
    {
  
  
    }
  
  }
  
  
And the calling code:
  
  
  public class Caller
  
  {
  
    public void Dispatch(AbstractMessage msg)
  
    {
  
      IMessageHandler handler = new MyHandler();
  
      handler.Handle(msg);
  
    }
  
  }
  
  
Doing this means that you don't need to specify the type of msg when you call the Handle method, allowing you to call handle with any sub-class of AbstractMessage. This of course reduce the scope of the generic type to the method level....
  
  
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment30</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment30</guid><pubDate>Mon, 14 Apr 2008 01:43:07 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>Actually, GetHandler's signature should be:
  
  
public static IMessageHandler GetHandler(AbstractMessage msg)
  
...
  
  
and the calling code updated accordingly.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment29</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment29</guid><pubDate>Sun, 13 Apr 2008 18:24:26 GMT</pubDate></item><item><title>Bryan Watts commented on Challenge: calling generics without the generic type</title><description>I created the non-generic IMessageHandler so we have something to call handlers when the type isn't known at compile-time.
  
  
I then created a static class, Messaging, to control the instantiation. Internally it defines a lambda which takes a type and returns a lambda which instantiates the message handler:
  
  
Func&lt;Type, Func&lt;IMessageHandler&gt;&gt; _handlerFactory;
  
  
I then memoize the lambda so it remembers the lambdas it returns for creating each message type, meeting the 1-time reflection goal.
  
  
(see http://www.infoq.com/news/2007/01/CSharp-memory)
  
  
You would use this as such:
  
  
public void Dispatch(AbstractMessage msg)
  
{
  
  IMessageHandler handler = Messaging.GetHandler(msg.GetType());
  
  
  handler.Handle(msg);
  
}
  
  
Source:
  
  
public interface IMessageHandler
  
{
  
	void Handle(AbstractMessage msg);
  
}
  
  
public interface IMessageHandler&lt;T&gt; : IMessageHandler where T : AbstractMessage
  
{
  
	new void Handle(T msg);
  
}
  
  
public class MessageHandler&lt;T&gt; : IMessageHandler&lt;T&gt;
  
{
  
	public void Handle(T msg)
  
	{
  
		...
  
	}
  
  
	void IMessageHandler.Handle(AbstractMessage msg)
  
	{
  
		// Single point of typing failure
  
		return Handle((T) msg);
  
	}
  
}
  
  
public static class Messaging
  
{
  
	private static Func&lt;Type, Func&lt;IMessageHandler&gt;&gt; _handlerFactory;
  
  
	static Messaging()
  
	{
  
		_handlerFactory = (type =&gt; GetHandlerCreator(type)).Memoize();
  
	}
  
  
	public static IMessageHandler GetHandler(Type messageType)
  
	{
  
		var creator = _handlerFactory(messageType);
  
  
		return creator();
  
	}
  
  
	private static Func&lt;IMessageHandler&gt; GetHandlerCreator(Type messageType)
  
	{
  
		var creator = Expression.Lambda&lt;Func&lt;IMessageHandler&gt;&gt;(
  
				Expression.New(typeof(MessageHandler&lt;&gt;).MakeGenericType(messageType)));
  
  
		return creator.Compile();
  
	}
  
}
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment28</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment28</guid><pubDate>Sun, 13 Apr 2008 18:07:29 GMT</pubDate></item><item><title>Tuna Toksoz commented on Challenge: calling generics without the generic type</title><description>Edit: ..using reflection in only one call of Dispatch method.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment27</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment27</guid><pubDate>Sun, 13 Apr 2008 15:38:26 GMT</pubDate></item><item><title>Tuna Toksoz commented on Challenge: calling generics without the generic type</title><description>@Pawel Pabich
  
If this would compile, there wont be this challenge practice. What we need to do is to find a way to create MyHandler'1 instance with msg.GetType() parameter with using generics in only one call of Dispatch method.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment26</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment26</guid><pubDate>Sun, 13 Apr 2008 15:20:56 GMT</pubDate></item><item><title>Stefan Wenig commented on Challenge: calling generics without the generic type</title><description>Reshef,
  
  
if you want to build a cache, you need the same type for every entry. If you only cache Action&lt;AbstractMessage&gt;, you'll have to create code that casts that AbstractMessage to whatever T really is.
  
  
Ayende,
  
  
you mean like class MyMsg2Handler : IMessageHandler&lt;MyMsg2&gt; ?
  
How would that affect the Dispatch method? Should it handle various message handler types, like, using a dictionary that maps message types to handler types? Or do you mean that MyHandler could be replaced by one single other class? What difference would that make? 
  
  
If it's necessary, I'd just create a c# 3.0 expression, compile it and store the resulting delegate in a dictionary. Composing and compiling Expressions is easier, more readable and more robust than Reflection.Emit.
  
  
- define a generic dispatch method (e.g. DoDispatch&lt;T&gt;) that does what your Dispatch method does, only statically typed, so you can limit code generation to calling that method
  
- create a lambda expression for (AbstractMessage) m =&gt; DoDispatch ((T) m) (writing this in C# syntax is a bit misleading, since that would require a return type, but dynamically it's legal)
  
- compile it to an Action&lt;AbstractMessage&gt;
  
- store it in a cache&lt;Type, Action&lt;AbstractMessage&gt;
  
  
Just a few lines of code. I still don't get the need for doing this, though.
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment25</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment25</guid><pubDate>Sun, 13 Apr 2008 15:16:51 GMT</pubDate></item><item><title>Pawel Pabich commented on Challenge: calling generics without the generic type</title><description>Why do you think that Kalpesh's solution is wrong ? As far as I know CLR will create a new type only once no matter how many different message types your application defines because AbstratMessage is a reference type.
  
  
BTW This won't compile :
  
IMessageHandler&lt;msg.GetType()&gt; handler = new MyHandler&lt;msg.GetType()&gt;();
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment24</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment24</guid><pubDate>Sun, 13 Apr 2008 15:14:35 GMT</pubDate></item><item><title>Reshef Mann commented on Challenge: calling generics without the generic type</title><description>Ok, instaed of LCG we can have a static factory method like this:
  
internal static IMessageHandler&lt;TMessage&gt; FactoryMethod&lt;TMessage&gt;() {
  
    return new MyHandler&lt;TMessage&gt;();
  
}
  
  
By reflection (on the first time) we will use 'MakeGenericMethod' with the type of the message, make a delegate out of it and cache it for each message type. In further calls we will use the cached factory method.
  
  
It is like what u did here: http://ayende.com/Blog/archive/2008/01/21/Challenge-Strongly-typing-weakly-typed-code.aspx
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment23</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment23</guid><pubDate>Sun, 13 Apr 2008 14:28:24 GMT</pubDate></item><item><title>Frans Bouma commented on Challenge: calling generics without the generic type</title><description>That's not what I meant :) IMessageHandler&lt;T&gt; implements IMessageHandler, and IMessageHandler has a Handle() method. 
  
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment22</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment22</guid><pubDate>Sun, 13 Apr 2008 13:32:33 GMT</pubDate></item><item><title>Romain Verdier commented on Challenge: calling generics without the generic type</title><description>If we consider the GetType() call for each message, the following solution may be a good starting point:
  
  
-----------------
  
public interface IMessageHandler&lt;T&gt; where T : AbstractMessage
  
{
  
   void Handle(T msg);
  
}
  
  
public class AbstractMessage
  
{
  
}
  
  
public class MessageA : AbstractMessage
  
{
  
  
}
  
  
public class MessageB : AbstractMessage
  
{
  
  
}
  
  
public class MyHandler&lt;T&gt; : IMessageHandler&lt;T&gt; where T : AbstractMessage
  
{
  
   public void  Handle(T msg)
  
   {
  
      Console.WriteLine(string.Format("'{0}' handled '{1}' message.", this.GetType(), msg.GetType()));
  
   }
  
}
  
  
public class Dispatcher
  
{
  
   private delegate void DispatchMessageDelegate(AbstractMessage msg);
  
  
   private readonly Dictionary&lt;Type, DispatchMessageDelegate&gt; dispatchers = new Dictionary&lt;Type, DispatchMessageDelegate&gt;();
  
  
   public void Dispatch(AbstractMessage msg)
  
   {
  
      var dispatcherDelegate = GetDispatchDelegate(msg.GetType());
  
        dispatcherDelegate(msg);
  
   }
  
  
   private DispatchMessageDelegate GetDispatchDelegate(Type messageType)
  
   {
  
      if (!this.dispatchers.ContainsKey(messageType))
  
      {
  
          var dispatchDelegate = GenerateDispatchDelegate(messageType);
  
         this.dispatchers[messageType] = dispatchDelegate;
  
      }
  
      return this.dispatchers[messageType];
  
   }
  
  
   private static DispatchMessageDelegate GenerateDispatchDelegate(Type messageType)
  
   {
  
      Console.WriteLine(string.Format("Use reflection for '{0}'.", messageType));
  
      var method = new DynamicMethod(string.Format("Dipatch{0}Message", messageType.Name),
  
                                       null,
  
                                       new[]{typeof(AbstractMessage)},
  
                                       typeof(Dispatcher));
  
  
      var gen = method.GetILGenerator();
  
  
      var closedHandlerType = typeof (IMessageHandler&lt;&gt;).MakeGenericType(messageType);
  
      var constructorInfo = typeof (MyHandler&lt;&gt;).MakeGenericType(messageType).GetConstructor(new Type[]{});
  
      var handleMethod = closedHandlerType.GetMethod("Handle");
  
  
      gen.DeclareLocal(closedHandlerType);
  
  
      gen.Emit(OpCodes.Nop);
  
      gen.Emit(OpCodes.Newobj, constructorInfo);
  
      gen.Emit(OpCodes.Stloc_0);
  
      gen.Emit(OpCodes.Ldloc_0);
  
      gen.Emit(OpCodes.Ldarg_0);
  
      gen.Emit(OpCodes.Castclass, messageType);
  
      gen.Emit(OpCodes.Callvirt, handleMethod);
  
      gen.Emit(OpCodes.Nop);
  
      gen.Emit(OpCodes.Ret);
  
  
      return (DispatchMessageDelegate) method.CreateDelegate(typeof (DispatchMessageDelegate));
  
   }
  
}
  
  
[TestFixture]
  
public class TestHandler
  
{
  
   [Test]
  
   public void ShouldWork()
  
   {
  
      var dispatcher = new Dispatcher();
  
      var messageA = new MessageA();
  
      var messageB = new MessageB();
  
  
      dispatcher.Dispatch(messageA);
  
      dispatcher.Dispatch(messageA);
  
      dispatcher.Dispatch(messageA);
  
      dispatcher.Dispatch(messageB);
  
      dispatcher.Dispatch(messageB);
  
      dispatcher.Dispatch(messageB);
  
   }
  
}
  
-----------------
  
  
Romain
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment21</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment21</guid><pubDate>Sun, 13 Apr 2008 13:26:34 GMT</pubDate></item><item><title>Ayende Rahien commented on Challenge: calling generics without the generic type</title><description>Andrew,
  
Dispatch cannot be a generic method call
</description><link>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment20</link><guid>http://ayende.com/3272/challenge-calling-generics-without-the-generic-type#comment20</guid><pubDate>Sun, 13 Apr 2008 12:28:14 GMT</pubDate></item></channel></rss>