如何使用事件数组处理传入的命令?(How to process incoming commands using event arrays?)

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

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

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

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

I'm currently working on a simple Client/Server model which sends packets within TCP packets (like HTTP) and the commands are basically ints (the first 4 bytes of each packet) and I'd like to work out an efficient way of how to process these commands.

The most obvious answer would be to write thousands of if's or do one huge switch statement with thousand cases, but isn't there any better way?

I'd like to create an array of events and then just raise the corresponding index so each int refers to one event which is named (such as MessageReceived). I'd also save time I think, so how could I work this out?

EDIT: The Server handles multiple connections, one for each client that is connected, so creating seperate connections for each command(s) isn't that useful in my case.

最满意答案

听起来像是一份工作!

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);

Sound like a job for enums!

enum YourEnum { DoThis, DoThat } YourEnum foo = (YourEnum)yourInt;

Visual studio can even create your entire switch statement using the built in snippets and your code becomes very readable.

switch(foo)

becomes

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

Update 1

This is a little scary from a maintainability point of view, but if you created a class like:

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() { }

or a little nicer but harder to maintain:

[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() { } }

Update 2 (Coding what I think Josh C. was talking about)

// 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; } }

This you create the SomeActionProcessor that is responsible for some value:

// 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() { } }

Then create the classes and wire them up:

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

The fire away and sending the generic processor requests:

gp.ProcessAction(1);

更多推荐