4

私は現在、TCP パケット (HTTP など) 内でパケットを送信する単純なクライアント/サーバー モデルに取り組んでおり、コマンドは基本的に int (各パケットの最初の 4 バイト) であり、効率的な方法を考えたいと思います。これらのコマンドを処理します。

最も明白な答えは、何千もの if を書くか、1 つの巨大な switch ステートメントを何千ものケースで実行することですが、他に良い方法はありませんか?

イベントの配列を作成し、対応するインデックスを上げて、各 int が名前付きの 1 つのイベント (MessageReceived など) を参照するようにしたいと思います。時間も節約できると思いますが、どうすればこれを解決できますか?

EDIT:サーバーは、接続されているクライアントごとに1つずつ、複数の接続を処理するため、コマンドごとに個別の接続を作成することは、私の場合はそれほど役に立ちません。

4

2 に答える 2

3

列挙型の仕事のように聞こえます!

enum YourEnum   
{
  DoThis,
  DoThat
}

YourEnum foo = (YourEnum)yourInt;

Visual Studio では、組み込みのスニペットを使用して switch ステートメント全体を作成することもでき、コードが非常に読みやすくなります。

switch(foo)

になる

switch(foo)
{
  case YourEnum.DoThis:
    break;
  case YourEnum.DoThat:
    break;
  default:
    break;
}

更新 1

これは保守性の観点からは少し怖いですが、次のようなクラスを作成した場合:

public class ActionProcessor
{
  public void Process(int yourInt)
  {
    var methods = this.GetType().GetMethods();
    if (methods.Length > yourInt)
    {
      methods[yourInt].Invoke(this, null);
    }
  }

  public DoThis()
  {
  }

  public DoThat()
  {
  }

または少し良いが維持するのが難しい:

[AttributeUsageAttribute(AttributeTargets.Method, 
                         Inherited = false, 
                         AllowMultiple = false)]
public sealed class AutoActionAttribute : Attribute
{ 
  public AutoActionAttibute(int methodID)
  {
    this.MethodID = methodID;
  }
  public int MethodID { get; set; }
}

public class ActionProcessor
{
  public void Process(int yourInt)
  {
    var method = this.GetType().GetMethods()
      .Where(x => x.GetCustomAttribute(typeof(AutoActionAttribute), 
                                       false) != null
                  && x.GetCustomAttribute(typeof(AutoActionAttribute), 
                                       false).MethodID == yourInt)
      .FirstOrDefault();

    if (method != null)
    {
      method.Invoke(this, null);
    }
  }

  [AutoAction(1)]
  public DoThis()
  {
  }

  [AutoAction(2)]
  public DoThat()
  {
  }
}

更新 2 (Josh C. が話していたと思われるコーディング)

// Handles all incoming requests.
public class GenericProcessor
{
  public delegate void ActionEventHandler(object sender, ActionEventArgs e);

  public event ActionEventHandler ActionEvent;

  public ProcessAction(int actionValue)
  {
    if (this.ActionEvent != null)
    {
      this.ActionEvent(this, new ActionEventArgs(actionValue));
    }
  }
}

// Definition of values for request
// Extend as needed
public class ActionEventArgs : EventArgs
{
  public ActionEventArgs(int actionValue)
  {
    this.ActionValue = actionValue;
  }

  public virtual int ActionValue { get; private set; }
}

これにより、何らかの値を担当する SomeActionProcessor を作成します。

// Handles a specific (or multiple) requests
public class SomeActionProcessor
{
  public void HandleActionEvent(object sender, ActionEventArgs e)
  {
    if (e.ActionValue == 1)
    {
      this.HandleAction();
    }
  }

  private void HandleAction()
  {
  }
}

次に、クラスを作成して接続します。

GenericProcessor gp = new GenericProcessor();
SomeActionProcessor sap = new SomeActionProcessor();
gp.ActionEvent += sap.HandleActionEvent;

発火し、一般的なプロセッサ要求を送信します。

gp.ProcessAction(1);
于 2012-10-08T22:22:17.223 に答える
1

パブリッシャー - サブスクライバー モデルを実装できる可能性があります。リスナーは 1 人ではなく、多数存在します。各リスナーは、少なくとも 1 つのコマンドをリッスンします。次に、スイッチを複数のクラスに分割できます。

于 2012-10-08T22:28:15.617 に答える