在C#中是否可以在基类的不同后代中重载具有不同签名的方法,然后根据重载方法的参数的运行时类型调用适当的方法?
作为背景,我正在处理消息处理过程,从编译时未知的消息类型开始,并且随着时间的推移,不同类型的消息处理功能将被添加。理想情况下,新的消息处理将更改子类,但不会更改基类。它现在可以通过在基类中包含所有类型化方法并根据消息类型显式选择正确的方法来正常工作。这个问题主要是出于好奇心,因为基于this question的答案,我希望它应该是可能的。如果我过于复杂,并且采用更简单的方法,我也欢迎这个建议。
示例代码如下所示,我希望每次调用 HandleTypedMessage(BaseMessage msg)和 HandleTypedMessage(MessageA msg),而不是 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");
}
}
答案 0 :(得分:2)
您正在对方法调用dynamic
进行不正确的部分。制作目标dynamic
,而不是参数:
((dynamic)handlerA).HandleTypedMessage(msga);
((dynamic)handlerA).HandleTypedMessage(msgb);
它会查找实际类型HandleTypedMessage
指向(handlerA
)的最佳匹配MessageHandlerA
方法,而不是它声明为(MessageHandler
)的方法。
以上代码打印
Handled message a
Did nothing with http://message/a
答案 1 :(得分:1)
一种方法是将dynamic
调度移动到处理程序子库中,如下所示:
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");
}
}