3

根据我的问题(通用方法的可重用非通用方法),我已经实现了提供的解决方案,但是经过一些重构(将代码移动到基类),我的代码导致了我不理解的 StackOverflowException。

Handle(new TestCommand())结果的调用IMessageHandler.Handle(IMessage)被调用,然后Handle<TMessage>(TMessage)被调用,但不是调用Handle(TestCommand message)继承的类,而是IMessageHandler.Handle(IMessage)再次调用。

泛型方法中的 as-cast toIMessageHandler<TestCommand>有效,否则它将调用HandleUnknownMessage(IMessage).

很难描述,所以这里是我的测试代码:

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 {    }

如果我将代码从我的基类ProcessBase放到MyProcess,代码可以正常工作。将动态关键字与泛型方法和继承结合使用是否有任何限制?

4

1 回答 1

3

尝试定义IMessageHandler<TMessage>一个void Handle<TMessage>(TMessage message)方法。

由于它没有被定义,你定义的MyProcess.Handle事件属于那个类而不属于它实现的接口。当您的代码尝试调用您的IMessageHandler<TMessage> handler时,它不知道它实际上是MyProcess具有这些特定方法的。添加接口方法后,调用解析应该识别出这些方法存在MyProcess并调用它们。否则它只会调用IMessageHandler.Handle(IMessage)产生无限循环的下一个最佳方法。

于 2012-12-18T12:20:18.223 回答