2017-10-17 55 views
2

的内容的我有一个基类,其处理从流接收的消息。现在我想检查收到的新消息是哪一个,并根据这个如何处理这个消息。使用属性取决于一类

然后我头的想法,代码会更好,如果我所创造的一切消息的一个基类,对个人信息有很多派生类的阅读。 (我有大约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();

获取数据,但这种感觉就像双重工作..

所以我问题是:如何使用从基类解析数据,靠的是在这个类什么样的内容属性?

要clearify我想要什么,我写了这个代码(这实际上不工作)

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

所以你目标是在你的代码中有大约100个派生类?也许是我的,但它肯定听起来像有它一个更好的方式比.. – Picnic8

+0

我认为没有什么不对的'如果(FUNC ...'你有,只是使它成为消息工厂,这将转换您的涌进消息实例,你是好恕我直言。然后就可以使用继承或只是一个接口为您的邮件类,将有像'.showMeData()',你是好,这样一来你的工厂是唯一的地方关心你正在实例化的是什么类 – user3012759

+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()); 
} 
+0

其他任何更好的 –

+1

@EhsanSajjad这是一个多派遣问题,它在OO语言中有很多解决方案,但都不是理想的,我已经使用了这个多年,现在它已经做了n个到目前为止我没有任何麻烦。 – dasblinkenlight