2014-02-15 6 views
1

Возможно ли, чтобы на C# был перегружен метод с разными сигнатурами в разных потомках базового класса, а затем вызывается соответствующий метод на основе типа времени выполнения аргумента перегруженного метода?Перегрузка метода повторного использования в разных классах

В качестве фона я работаю над процессом обработки сообщений, начиная с точки, где тип сообщения неизвестен во время компиляции, и с различными функциями обработки сообщений, которые должны быть добавлены для разных типов с течением времени. Идеально новая обработка сообщений изменила бы подкласс, но не базовый класс. Теперь он отлично работает, включая все типизированные методы в базовом классе и явно выбирает правильный, основанный на типе сообщения. Вопрос вызван главным образом любопытством, поскольку на основании ответа на вопрос this question Я ожидаю, что это будет возможно. Если я смущаю это, и theres более простой подход, я бы тоже приветствовал этот совет.

Пример кода, показывающий это ниже, я ожидал HandleTypedMessage (BaseMessage тзд) и HandleTypedMessage (MessageA тзд) называть один раз, а не HandleTypedMessage (BaseMessage MSG) вызывается дважды.

class Program 
{ 
    static void Main(string[] args) 
    { 
     var msga = new MessageA(); 
     var msgb = new MessageB(); 
     MessageHandler handlerA = new MessageHandlerA(); 

     handlerA.HandleTypedMessage((dynamic) msga); 

     handlerA.HandleTypedMessage((dynamic) msgb); 

     Console.ReadLine(); 
    } 
} 

public interface IHandlesMessage 
{ 
    void HandleMessage(BaseMessage message); 
} 

public abstract class BaseMessage 
{ 
    public abstract string MessageType { get; } 
} 

public class MessageA : BaseMessage 
{ 
    public override string MessageType 
    { 
     get { return "http://message/a"; } 
    } 
} 

public class MessageB : BaseMessage 
{ 
    public override string MessageType 
    { 
     get { return "http://message/a"; } 
    } 
} 

public abstract class MessageHandler 
{ 
    public abstract void HandleTypedMessage(BaseMessage msg); 
} 

public class MessageHandlerA : MessageHandler 
{ 
    public override void HandleTypedMessage(BaseMessage msg) 
    { 
     Console.WriteLine("Did nothing with " + msg.MessageType); 
    } 

    public void HandleTypedMessage(MessageA msg) 
    { 
     Console.WriteLine("Handled message a"); 
    } 

} 

public class MessageHandlerB : MessageHandler 
{ 
    public override void HandleTypedMessage(BaseMessage msg) 
    { 
     throw new NotImplementedException(); 
    } 

    public void HandleTypedMessage(MessageB msg) 
    { 
     System.Console.WriteLine("Handled message b"); 
    } 
} 

ответ

2

Вы делаете неправильную часть своего вызова метода dynamic. Сделать цель dynamic, а не параметр:

((dynamic)handlerA).HandleTypedMessage(msga); 
((dynamic)handlerA).HandleTypedMessage(msgb); 

Он будет искать наиболее подходящий HandleTypedMessage метод для фактического типа handlerA очков (MessageHandlerA), а не тот, он объявлен как (MessageHandler).

Код выше принтами

Handled message a 
Did nothing with http://message/a 
+0

Perfect. Просто заметил, что я оставил одно и то же свойство MessageType в обоих классах сообщений, но ясно, что происходит. – Rattle

1

Один подход заключается в перемещении dynamic отправки в sublcasses обработчика, как это:

public class MessageHandlerA : MessageHandler { 
    public override void HandleTypedMessage(BaseMessage msg) { 
     this.HandleTypedMessageCore((dynamic) msg); 
    } 

    private void HandleTypedMessageCore(BaseMessage msg) { 
     Console.WriteLine("Did nothing with " + msg.MessageType); 
    } 

    private void HandleTypedMessageCore(MessageA msg) { 
     Console.WriteLine("Handled message a"); 
    } 
} 
+0

Спасибо - это работает, но я принял ответ Марцина, поскольку изменение стало проще. – Rattle

Смежные вопросы