我有一个基类来处理从流中接收的消息。现在我想检查是否收到了一条新消息,它是哪一条消息,具体取决于如何处理此消息。
然后我理解这个想法,如果我为所有消息创建一个Base类,并为各个消息创建大量派生类,那么代码会更好。 (我有大约100个不同的消息要处理)
这里的问题:我们不能将基类转换为派生类(参见Convert base class to derived class)这是完全合乎逻辑的,我理解为什么它必须像这样。但我实际上不需要一个“整个”类,我只需要一个名称不同的属性,具体取决于收到的消息,它解析基类中的数据。但我也不希望每个属性都写成public byte Message02_Value1 => Data[0]
。我想使用这个语法:MessageBaseClass.Message01.Value
我还可以在从流中获取数据时编写代码
if (function == 1)
new MessageBaseClass.Message01();
if (function == 2)
new MessageBaseClass.Message02();
但这感觉就像双重工作..
所以我的问题是:我如何使用解析基类数据的属性,具体取决于此类中的内容类型?
要清除我想要的东西,我写了这段代码(实际上不起作用)
class Program
{
static void Main(string[] args)
{
Msg[] messages =
{
new Msg { Function = 1, Data = new byte[] { 1, 2, 3, 4 } } ,
new Msg { Function = 2, Data = new byte[] { 1, 2, 3, 4 } }
};
foreach (Msg msg in messages)
{
switch (msg.Function)
{
case 1:
var Message1 = msg as Msg.Message01;//Error, is not able to convert --> Message1 == null
Console.WriteLine($"Serial: {Message1.Serial}");
break;
case 2:
var Message2 = msg as Msg.Message02;//Error, is not able to convert --> Message2 == null
Console.WriteLine($"Value1: {Message2.Value1}" +
$"Value2: {Message2.Value2}" +
$"Value3: {Message2.Value3}");
break;
}
}
}
class Msg
{
public byte Function { get; set; }
public byte[] Data { get; set; }
public class Message01 : Msg
{
public uint Serial => BitConverter.ToUInt32(Data, 0);
}
public class Message02 : Msg
{
public byte Value1 => Data[0];
public byte Value2 => Data[1];
public ushort Value3 => BitConverter.ToUInt16(Data, 2);
}
}
}
答案 0 :(得分:4)
您尝试采用的方法基本上是错误的,原因与打开类的运行时类型错误的原因相同。从本质上讲,你正在做同样的事情,用一个数字代码替换一个类型。
C#为处理子类提供了一个非常好的选项,无需明确调度类型:为各个类型设置重载,将消息转换为dynamic
,让C#为您调用正确的重载:
void ProcessMessages(IEnumerable<Msg> messages) {
foreach (var m in messages) {
ProcessSingleMessage((dynamic)m);
}
}
void ProcessSingleMessage(Message1 m1) {
// Access properties of m1 as needed
}
void ProcessSingleMessage(Message2 m2) {
// Access properties of m2 as needed
}
...
// Catch-all handler
void ProcessSingleMessage(Msg m) {
throw new InvalidOperationException("Received a message of unknown type: "+m.GetType());
}