根据类的内容使用属性

时间:2017-10-17 14:41:33

标签: c# oop

我有一个基类来处理从流中接收的消息。现在我想检查是否收到了一条新消息,它是哪一条消息,具体取决于如何处理此消息。

然后我理解这个想法,如果我为所有消息创建一个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);
            }
        }
    }

1 个答案:

答案 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());
}