According to my question (Reusable non generic method for generic methods) i have implemented the provided solution, but after some refactoring (moving code to base class) my code results in a StackOverflowException that i don´t understand.
The call to Handle(new TestCommand()) results in that IMessageHandler.Handle(IMessage) gets called and then Handle<TMessage>(TMessage) gets called, but instead of calling Handle(TestCommand message) of the inherited class it calls IMessageHandler.Handle(IMessage) again.
The as-cast to IMessageHandler<TestCommand> in the generic method works, otherwise it would call HandleUnknownMessage(IMessage).
Its hard to describe so instead here´s my TestCode:
class Program {
static void Main(string[] args) {
MyProcess p = new MyProcess();
IMessageHandler handler = p;
handler.Handle(new DummyCommand()); // works -> HandleUnknownMessage gets called as expected
handler.Handle(new TestCommand()); // fails -> results in a StackOverflowException
}
}
public abstract class ProcessBase : IMessageHandler {
void IMessageHandler.Handle(IMessage message) {
System.Diagnostics.Debug.WriteLine("Dynamic Message gets handled");
dynamic dynamicMessage = message;
Handle(dynamicMessage);
}
private void Handle<TMessage>(TMessage message) where TMessage : IMessage {
System.Diagnostics.Debug.WriteLine("Generic Message gets handled");
var handler = this as IMessageHandler<TMessage>;
if (handler == null)
HandleUnknownMessage(message);
else
handler.Handle(message);
}
protected virtual void HandleUnknownMessage(IMessage unknownMessage) {
System.Diagnostics.Debug.WriteLine("Unknown message {0} passed to Process".FormatWith(unknownMessage.GetType()));
// Handle unknown message types here.
}
}
public class MyProcess : ProcessBase, IMessageHandler<TestCommand>, IMessageHandler<TestEvent> {
public void Handle(TestCommand commandMessage) {
System.Diagnostics.Debug.WriteLine("TestCommand gets handled");
}
public void Handle(TestEvent eventMessage) {
System.Diagnostics.Debug.WriteLine("TestEvent gets handled");
}
}
public class DummyCommand : IMessage { }
public class TestCommand : IMessage { }
If i put the code from my base class ProcessBase to MyProcess, the code works without problem. Are there any limitations in use of the dynamic keyword in conjuction with generic methods and inheritance?
Try defining on
IMessageHandler<TMessage>avoid Handle<TMessage>(TMessage message)method.Since it’s not defined, your
MyProcess.Handleevents that you’ve defined belong only to that class and not to the interfaces it implements. When your code attempts to call on yourIMessageHandler<TMessage> handler, it doesn’t know that it’s actually aMyProcessthat has those specific methods. Once you add the interface method, the call resolution should recognize that those methods exist onMyProcessand call them. Otherwise it just calls the next best method beingIMessageHandler.Handle(IMessage)which produces an infinite loop.