2017-10-17 54 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