Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在一个类中处理多个方法的最佳方法是什么?_C#_Oop_Design Patterns - Fatal编程技术网

C# 在一个类中处理多个方法的最佳方法是什么?

C# 在一个类中处理多个方法的最佳方法是什么?,c#,oop,design-patterns,C#,Oop,Design Patterns,我正在用C#制作一个服务器,我有一个处理数组中所有登录用户的单例。该数组是名为UserSession的类的数组 这个UserSession类有一个在单独线程上运行的方法,该线程处理该用户的传入数据包 嗯,考虑这个代码: class UserSession { public UserSession(TcpClient client) { var thread = new Thread(new ParameterizedThreadStart(HandleComm);

我正在用C#制作一个服务器,我有一个处理数组中所有登录用户的单例。该数组是名为UserSession的类的数组

这个UserSession类有一个在单独线程上运行的方法,该线程处理该用户的传入数据包

嗯,考虑这个代码:

class UserSession
{
    public UserSession(TcpClient client)
    {
        var thread = new Thread(new ParameterizedThreadStart(HandleComm);
        thread.Start((object)client);
    }

    public void HandleComm(object tcpClient)
    {
        TcpClient client = (TcpClient)tcpClient;
        NetworkStream stream = client.GetStream();
        while(1 == 1)
        {
            byte[] buffer = new byte[4096];
            stream.Read(buffer, 0, buffer.Length);
            int testShort = Convert.ToInt32(buffer);
            switch((ActionEnum)testShort)
            {
                case ActionEnum.Something:
                    // here is my problem!
                    // do some more parsing of the message
                    this.DoSomething(SomethingStruct argument); // argument taken from the byte array
                    break;
                case ActionEnum.AnotherSomething:
                    // the same as before
                    break;
                // and this goes on and on
            }
        }
    }
}
处理所有这些单独的枚举而不重复使用该类上的80多个方法的最佳方法是什么?(ActionEnum是具有当前用户特定操作的枚举)


我序列化了缓冲区,我只是让代码快速运行,让您有一个想法。

像往常一样,有很多可能的答案。我在构建客户机/服务器游戏时遇到了这个问题。我从几十个动作/事件/消息的枚举开始,然后意识到当你进行大量的动作时,这是不可持续的

这是我在伪代码中大致做的

    NetworkClass 
    {
       RegisterChannel(objUsingChannel,typeOfChannel, callbackForChannel, expectedReturnType){/*...*/};

       PushChannelMsg(channelID, dataToSend)

       ReceiveMessageFromNetwork(msg){  Read data from network, which also contains channelID, and send it to any matching channelID}  
       //If there is no channel registered for a data that is received,  just ignore it
    }

EnemyTurretObject
{
   //Register the rotation channel and listen for rotation changes
   NetworkClass.RegisterChannel(this, channels.TurretRotated + this.ID, callback=HandleTurretRotated, doubleReturnType)

   HandleTurretRotated(double rot)
   {  rotate the turret  }
}

FriendlyTurretObject
{
   //Register two channels that we'll send data across
   NetworkClass.RegisterChannel(this, channels.TurretFired + this.ID, callback=null, MissleFiredData)
   NetworkClass.RegisterChannel(this, channels.TurretRotated + this.ID, callback=null, doubleDataType)

   FireMissle()
    {
       NetworkClass.PushChannelMsg(channels.TurretFired + this.ID, new MissleFiredData(x,y)) 
    }

    RotateTurret()
    {
      NetworkClass.PushChannelMsg(channels.TurretRotated + this.ID, newTurretRotationValue) 
    }

}

我基本上避免了大量的枚举,并进行了更一般化的设置,以便每个对象负责自己的数据、通道等。这是一种更加灵活的方法,更改一个枚举并不会破坏一切。network类甚至不需要知道所发送的数据中有什么,它现在只是一个管道。

因此:您基本上是在尝试这样做,将数字代码转换为方法调用

有些事情是你无法得到的,比如自动完成转换。如果您传输了方法的名称,那么您可以使用反射来查找方法,然后调用它。因此,您必须执行一些手动工作来建立映射

然后你要决定的是将数字映射到方法的最佳方式

一种方法就是您现在使用的方法。在这里,映射发生在调度周期内(获取编号、转换、调用)。问题是映射代码掩盖了调度代码。还有相当数量的样板代码

您可以使用命令模式和哈希映射的组合,如下所示:

在安装过程中:

  • 为命令创建公共接口(或使用闭包,因为 您正在使用C#)
  • 创建实现要映射的接口pr.方法的对象实例
  • 将其添加到hashmap
  • 在调度循环中:

  • 取数
  • 在哈希表中查找数字
  • 如果找到,则调用映射对象,否则失败
  • 一种更灵活的方法,将数字视为必须处理的消息,并使用职责链模式。 命令模式


    责任链

    为什么你的班级
    UserSession
    是单身?它有一个公共构造函数,希望您能够处理stream.Read()在生产代码中返回的任何内容。至于问题,有很多方法有什么问题?如果您只执行几行代码,那么处理可能会停留在案例本身内部;否则,它可能需要一种方法。upd:如果您的对象是统一序列化的,那么它实际上可能是一个以传入消息格式的某种描述作为参数的方法。@Habib.OSU我在一个名为LoggedUsers的类中有一个UserSession数组,它是一个singleton@EugeneRyabtsev根据ActionEnum,我有几个结构。我的问题是,管理我的代码的最佳方式是什么,这样它就可以正确地完成,而不是像一团乱麻一样,用200多个方法分别处理每一件事情。也是的,我处理我班上的一切。这只是一个快速的草图,向您展示了巨大的switch.NET序列化程序是统一的,并且使用了反射,因此它可以与流和typeof(struct)共存,并返回该结构。您可以复制它,具体取决于事物的序列化方式。我知道序列化格式不在您的控制范围之内,否则整个事情看起来会很奇怪。当您收到来自用户的数据包时,您会怎么做?假设你有不同的行为,比如“连接”或“断开”。您有很多不同的连接吗?连接和断开的处理更加具体。这些类型的案例不必在我上面描述的消息传递系统中。是的,我可以支持数百个连接。当接收到消息时,我基本上读取ChannelID,然后查看通道所期望的数据类型,然后将有效负载读取到预期返回类型的新实例中。采用这种方法将需要大量重构/重写网络代码。然而,我可以说,我在修改代码时获得的价值是巨大的。现在添加新的操作/类型/事件非常容易,整个网络代码至少减少了一半,而且简单性使调试和管理变得更加容易这就是我要做的。有一个映射将枚举值映射到方法,并查找和调用它们。这也是我解决这种情况的方法。它很好地分离了关注点,并促进了命令模式的使用。