2012-12-18 24 views
3

根據我的question(可重複使用的非泛型方法的泛型方法)我已經實現了提供的解決方案,但經過一些重構(將代碼移到基類)我的代碼結果在我不明白的StackOverflowException中。使用動態關鍵字和在基類結果調用泛型方法結果在StackOverflowException

Handle(new TestCommand())結果在IMessageHandler.Handle(IMessage)呼叫被稱爲然後Handle<TMessage>(TMessage)被調用,而不是調用繼承類的Handle(TestCommand message)它調用IMessageHandler.Handle(IMessage)一次。

通用方法中的鑄造爲IMessageHandler<TestCommand>的作品,否則它會調用HandleUnknownMessage(IMessage)

它很難這樣反而here's形容我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 { } 

如果我把代碼從我的基類ProcessBaseMyProcess,代碼工作沒有問題。使用動態關鍵字與泛型方法和繼承結合使用時是否有任何限制?

+1

'IMessageHandler '定義了'Handle (T)'方法嗎?編輯:你可以發佈'IMessageHandler'和'IMessageHandler '? –

+1

@Chris Sinclair:該死,你說得對。我錯過了在IMessageHandler 上定義Handle 。 – Jehof

+0

沒問題。我必須記住這個技巧;這是將運行時調用提升爲編譯時通用調用的一種巧妙方式。 (我會建議在'ProcessBase'上重命名私有的'處理'方法,以避免在方法解析時產生毛病) –

回答

3

嘗試定義IMessageHandler<TMessage> a void Handle<TMessage>(TMessage message)方法。

由於沒有定義,您定義的MyProcess.Handle事件屬於只有而不是它實現的接口。當你的代碼試圖調用你的IMessageHandler<TMessage> handler時,它不知道它實際上是具有這些特定方法的MyProcess。一旦添加接口方法,呼叫解析應該認識到這些方法存在於MyProcess並調用它們。否則,它只是調用下一個最好的方法,即產生無限循環的IMessageHandler.Handle(IMessage)

+0

感謝您的幫助。 – Jehof

相關問題