2017-10-17 6 views
2

私はストリームから受け取ったメッセージを扱う基本クラスを持っています。今度は、新しいメッセージが受信されたかどうかを確認したいのですが、これはこのメッセージの処理方法によって異なります。クラスの内容に応じたプロパティを使用する

次に、すべてのメッセージ用に1つのBaseクラスを作成し、個々のメッセージ用に多くの派生クラスを作成すると、コードを読みやすくする方がよいでしょう。 (私は処理する約100種類のメッセージがあります)

ここでの問題:基本クラスを派生クラス(Convert base class to derived classを参照)に変換することはできません。これは論理的な論理です。なぜこのようにしなければならないのか理解しています。しかし、私は本当に "全体"クラスを必要としません、私はちょうど別の名前が付いているプロパティを必要とする、受信したメッセージに応じて、ベースクラスからデータを解析します。しかし、私はまた、すべてのプロパティはpublic byte Message02_Value1 => Data[0]のように書かれたクラスwhithを望んでいない。だから私の

...それはストリーム

if (function == 1) new MessageBaseClass.Message01(); if (function == 2) new MessageBaseClass.Message02();

からデータを取得している間MessageBaseClass.Message01.Value

私はまた、コードを書くことができるが、これは二重の作品のように感じている:私はこの構文を使用したいです質問は:どのような種類のコンテンツがこのクラスにあるかに応じて、基本クラスのデータを解析するプロパティを使用するにはどうすればよいですか?

(実際には動作しません)私はこのコードを書いた何をしたい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

私は 'if(func ...'には何も問題はないと思います。メッセージファクトリに入れてくださいストリームをメッセージインスタンスに入れて、あなたは良いimhoです。そして、 '.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これは複数のディスパッチの問題です.On言語では多くのソリューションがありますが、いずれも理想的ではありません。私には今まで何のトラブルも起こっていません。 – dasblinkenlight

関連する問題