如果我正确理解您的问题,您确实有两个问题:
当您收到名称而不使用switch 时如何创建正确的 PDU。
使用字典Dictionary<string, Func<PduBase>>创建一个简单的工厂
调用public BasePdu ReceiveNext();的方法如何在不使用switch的情况下正确处理
不要使用RecieveNext 方法。为接收所有 PDU 的类创建一个AddPduHandler<T>(IPduHandler<T> handler) where T : PduBase 方法。将所有处理程序存储在字典中,类型为键:Dictionary<Type, Delegate>
存储委托是一种技巧,因为您不能在接收类中使用类型化接口。
更新
此解决方案不会违反所有使用 switch 的实现的 Liskovs 替换原则。这意味着无论你有多少不同类型的 PDU,这个类都可以工作。
测试您的应用程序也更容易,因为每个处理程序都与其他所有处理程序隔离。
好处是所有东西都是类型化的(除了阅读器类),这将更容易找到错误,而不是使用施法魔法等。
public class Receiver
{
Dictionary<Type, MethodMapping> _handlers = new Dictionary<Type, MethodMapping>();
Dictionary<string, Func<PduBase>> _factories = new Dictionary<string, Func<PduBase>>();
// Small container making it easier to invoke each handler
// also needed since different generic types cannot be stored in the same
// dictionary
private class MethodMapping
{
public object Instance { get; set; }
public MethodInfo Method { get; set; }
public void Invoke(PduBase pdu)
{
Method.Invoke(Instance, new[] {pdu});
}
}
// add a method used to create a certain PDU type
public void AddFactory(string name, Func<PduBase> factoryMethod)
{
_factories.Add(name, factoryMethod);
}
// register a class that handles a specific PDU type
// we need to juggle a bit with reflection to be able to invoke it
// hence everything is type safe outside this class, but not internally.
// but that should be a sacrifice we can live with.
public void Register<T>(IPduHandler<T> handler) where T : PduBase
{
var method = handler.GetType().GetMethod("Handle", new Type[] { typeof(T) });
_handlers.Add(typeof(T), new MethodMapping{Instance = handler, Method = method});
}
// fake that we've received a new PDU
public void FakeReceive(string pduName)
{
// create the PDU using the factory method
var pdu = _factories[pduName]();
// and invoke the handler.
_handlers[pdu.GetType()].Invoke(pdu);
}
}
public interface IPduHandler<in T> where T: PduBase
{
void Handle(T pdu);
}
public class TempPdu : PduBase
{}
public class TempPduHandler : IPduHandler<TempPdu>
{
public void Handle(TempPdu pdu)
{
Console.WriteLine("Handling pdu");
}
}
public class PduBase
{ }
private static void Main(string[] args)
{
Receiver r = new Receiver();
r.AddFactory("temp", () => new TempPdu());
r.Register(new TempPduHandler());
// we've recieved a PDU called "temp".
r.FakeReceive("temp");
}