4

我目前正在研究一个简单的客户端/服务器模型,它在 TCP 数据包(如 HTTP)中发送数据包,命令基本上是整数(每个数据包的前 4 个字节),我想找出一种有效的方法处理这些命令。

最明显的答案是编写数千个 if 或用数千个案例做一个巨大的 switch 语句,但没有更好的方法吗?

我想创建一个事件数组,然后只提高相应的索引,以便每个 int 引用一个名为的事件(例如 MessageReceived)。我想我也会节省时间,所以我怎么能解决这个问题?

编辑:服务器处理多个连接,每个连接的客户端一个,因此在我的情况下为每个命令创建单独的连接并不是那么有用。

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

您可能会实现发布者-订阅者模型。您将拥有许多听众,而不是只有一个听众。每个侦听器至少会侦听一个命令。然后,您可以将您的交换机拆分为多个类。

于 2012-10-08T22:28:15.617 回答