【发布时间】:2018-03-29 07:19:23
【问题描述】:
我有一个处理从流中接收到的消息的基类。现在我想检查是否收到了一条新消息,它是哪条消息以及如何处理这条消息。
然后我提出这个想法,如果我为所有消息创建一个基类并为单个消息创建许多派生类,则代码会更好阅读。 (我有大约 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);
}
}
}
【问题讨论】:
-
所以你的目标是在你的代码中有大约 100 个派生类?也许是我,但听起来肯定有比这更好的方法..
-
我认为您拥有的
if (func...没有任何问题,只需将其放入消息工厂,将您的流转换为消息实例,恕我直言。然后你可以为你的消息类使用继承或只是一个接口,它会有类似.showMeData()的东西,你很好,这样你的工厂是唯一关心你实例化什么类的地方。 -
为了维护,生成代码可能会更好。即使您/我们提出了一个很棒的设计,生成代码也会大大减少消息更改的影响