C# 实施一套「;福斯;其中有一个子集为;酒吧;在C中#

C# 实施一套「;福斯;其中有一个子集为;酒吧;在C中#,c#,oop,casting,object-oriented-analysis,C#,Oop,Casting,Object Oriented Analysis,我正在编写一个服务器来处理从客户端到主机的不同类型的消息。消息的内容和长度各不相同,前面会有一个标识符,以标识消息的类型。一些消息(例如,类型A、B和C)应该在机器之间转发。其他(例如类型D、E和F)需要服务器执行特定操作:即,它们不只是转发 (注意:两端的客户端需要区分A、B和C,但服务器只需要知道如何转发这些消息。服务器和客户端都需要能够区分D、E和F。) 我试图找到一个很好的面向对象的范例,用于表示消息的“类型”。因此,为了澄清这一点,假设服务器收到一条标记为“Type B”的消息,它只需

我正在编写一个服务器来处理从客户端到主机的不同类型的消息。消息的内容和长度各不相同,前面会有一个标识符,以标识消息的类型。一些消息(例如,类型A、B和C)应该在机器之间转发。其他(例如类型D、E和F)需要服务器执行特定操作:即,它们不只是转发

(注意:两端的客户端需要区分A、B和C,但服务器只需要知道如何转发这些消息。服务器和客户端都需要能够区分D、E和F。)

我试图找到一个很好的面向对象的范例,用于表示消息的“类型”。因此,为了澄清这一点,假设服务器收到一条标记为“Type B”的消息,它只需将该消息转发给相应的客户端即可。但是,如果它收到标记为“F型”的消息,它将采取不同的、特定的操作。那么,如何在代码中表示“类型”

我想要实现的理想解决方案是这样的;枚举“类型”,其中命令的某个子集属于“可转发”类型。显然这是不可能的,所以我想到了一个静态类,Forwardable,它继承自一个静态基类Type。同样,不可能。接口是可能的,但我真的不想为了解释类型而实例化实例

让服务器解析消息的最直接方法如下:

byte[] payload = GetPayload((byte[])rawMessage);
Type message = GetMessageType((byte[])rawMessage);
if(message is Forwardable)
{
  ForwardMessage(payload);
}
else
{
  switch(message)
   case 1:
     //
     break;
   case 2:
     //
     break;
}
最后,什么是表示一组类型的正确OO方式,其中这些类型的子集是一个子类型

编辑: 在某种程度上,我觉得这应该通过定义一个“类型”的静态类和定义另一个从“类型”继承的静态类(称为“Forwardable”)来实现。然后,我可以将我的服务器接收的内容转换为“类型”,并说如果(头是可转发的)。但不幸的是,您不能从静态类继承

这样行吗

enum ActionType
{
    Forwardable, ....
}

class Message //could be abstract, then make classes A : Message, B: Message etc with appropriate fields
{
    private Byte[] payload;

    public ActionType CurrentActionType {get;private set;}

    public Message(byte[] rawmessage)
    {
        //parse message's header to determine ActionType
        //parse rest of message and save to payload or other variables in inherited classes
    }
}

Message msg = new Message((byte[])rawMessage);
switch(msg.CurrentActionType)
{
    case ActionType.Forwardable :
        ForwardMessage(msg); break;
    case...
    case...
}
编辑
应转发
功能如评论中所述:

private Boolean ShouldForward(Message msg)
{
    switch(msg.CurrentActionType)
    {
        case ActionType.A:
        case ActionType.B:
        case ActionType.C:
            return true;
        default:
            return false;
    }
}

这里有一个想法,把东西包起来,这样你就可以把它们传给别人了。您可以定义MessageType来包装整个消息加载和标识,PayloadType来包装各种负载,子类ForwardMessage、ArchiveMessage来标识不同类型的负载

  • Message负责获取原始流输入

  • PayloadType负责加载其子类和公共类
    字段,包括MessageType

  • ForwardMessage、ArchiveMessage负责任何业务逻辑,但它们不负责 必须了解从流中加载自身的任何信息。实施 对于不同类型的有效载荷,更多的是这些
使用示例代码:

Message msg = Message.FromStream(stream);
PayloadType payload = msg.GetPayload();
payload.Process();
public class Message{
      public int Prefix {get; private set;}
      public byte[] RawPayload {get;private set;}

      public PayloadType GetPayload(){
        PayloadType result = null;
        switch (Prefix){ // you can also convert that to enum and use "if" for more complicated identification
          case 1: 
            result = PayloadType.FromRaw<ForwardMessage>(RawPayload);
            break;
          case 2: 
            result = PayloadType.FromRaw<ArchiveMessage>(RawPayload);
            break;
          default:
            break;
        }
      }

      public static Message FromStream(Stream s){
        Prefix = ReadTwoBytes(s);
        RawPayload = ReadToEnd(s);
      }
    }

    public abstract class PayloadType{
      public abstract MessageType MessageType {get;} // enum goes better here
      public abstract Process();

      public static T FromRaw(byte[] raw) where T: PayloadType{
        // deserialize this as you wish
        // such as:
        using (MemoryStream s = new MemoryStream(raw)){
          XmlSerializer xser = new XmlSerializer(typeof(T));
          return xser.Deserialize(s) as T; 
        }
      }
    }

    public ForwardMessage : PayloadType{
      public override MessageType MessageType {return MessageType.Forward;}
      public override Process(){
          // send this message elsewhere
      }
    }

    public ArchiveMessage: PayloadType{
      public override MessageType MessageType {return MessageType.Archive;}
      public override Process(){
           // store this message somehow
      }
    }

    public enum MessageType{
        Unknown, Formward, Archive,
    }
以下是示例代码:

Message msg = Message.FromStream(stream);
PayloadType payload = msg.GetPayload();
payload.Process();
public class Message{
      public int Prefix {get; private set;}
      public byte[] RawPayload {get;private set;}

      public PayloadType GetPayload(){
        PayloadType result = null;
        switch (Prefix){ // you can also convert that to enum and use "if" for more complicated identification
          case 1: 
            result = PayloadType.FromRaw<ForwardMessage>(RawPayload);
            break;
          case 2: 
            result = PayloadType.FromRaw<ArchiveMessage>(RawPayload);
            break;
          default:
            break;
        }
      }

      public static Message FromStream(Stream s){
        Prefix = ReadTwoBytes(s);
        RawPayload = ReadToEnd(s);
      }
    }

    public abstract class PayloadType{
      public abstract MessageType MessageType {get;} // enum goes better here
      public abstract Process();

      public static T FromRaw(byte[] raw) where T: PayloadType{
        // deserialize this as you wish
        // such as:
        using (MemoryStream s = new MemoryStream(raw)){
          XmlSerializer xser = new XmlSerializer(typeof(T));
          return xser.Deserialize(s) as T; 
        }
      }
    }

    public ForwardMessage : PayloadType{
      public override MessageType MessageType {return MessageType.Forward;}
      public override Process(){
          // send this message elsewhere
      }
    }

    public ArchiveMessage: PayloadType{
      public override MessageType MessageType {return MessageType.Archive;}
      public override Process(){
           // store this message somehow
      }
    }

    public enum MessageType{
        Unknown, Formward, Archive,
    }
公共类消息{
公共int前缀{get;private set;}
公共字节[]RawPayload{get;private set;}
公共PayloadType GetPayload(){
PayloadType结果=null;
开关(前缀){//您还可以将其转换为enum,并使用“if”进行更复杂的标识
案例1:
结果=PayloadType.FromRaw(原始有效载荷);
打破
案例2:
结果=PayloadType.FromRaw(原始有效载荷);
打破
违约:
打破
}
}
来自流的公共静态消息(流s){
前缀=读取两个字节;
RawPayload=读取结束(s);
}
}
公共抽象类PayloadType{
公共抽象MessageType MessageType{get;}//enum在这里更好
公共抽象过程();
公共静态T FromRaw(字节[]raw),其中T:PayloadType{
//如您所愿反序列化此文件
//例如:
使用(MemoryStream s=新的MemoryStream(原始)){
XmlSerializer xser=新的XmlSerializer(typeof(T));
返回xser.反序列化为T;
}
}
}
公共转发消息:PayloadType{
公共重写MessageType MessageType{return MessageType.Forward;}
公共覆盖过程(){
//将此消息发送到其他地方
}
}
公共存档消息:PayloadType{
公共重写MessageType MessageType{return MessageType.Archive;}
公共覆盖过程(){
//以某种方式存储此消息
}
}
公共枚举消息类型{
未知、形式化、归档、,
}
或第二种解决方案:

public interface Forwardable
{ }

public class A : Forwardable
{ }

public class F
{ }
还是第三种解决方案

byte[] payload = GetPayload((byte[])rawMessage);
Type message = GetMessageType((byte[])rawMessage);
if(IsForwardable((byte[])rawMessage))
{
  ForwardMessage(payload);
}
else
{
  TakeAppropriateAction(message, payload);
}

为每种处理类型(转发、删除等)创建一个类,然后用一个自定义的.NET属性来装饰它们,并实现一个已知的接口,怎么样

[MessageProcessor("TypeB")]
public class TypeBMessageProcessor : IMessageProcessor
{
  void IMessageProcessor.Process(byte[] message)
  {
     ....
  }
}
然后,您可以在应用程序启动时扫描程序集,找到用自定义MessageProcessorAttribute修饰的类,然后将该类型存储在由某类MessageProcessorFactory类持有的属性上的“TypeB”参数键入的字典中

然后,您可以在处理消息时创建该类型的实例

var processor = MessageProcessorFactory.GetProcessor("TheTypeCodePrecedingTheData");
processor.Process(messageData);

考虑到你的问题,我会做以下几点:

  • 对每条消息使用对象表示
  • 使用类似的模式根据消息类型处理消息
这种体系结构的优点是,您可以将每种消息类型的处理逻辑分开。这允许您快速扩展它(添加新的消息处理程序或新的消息类型),而不会影响系统的其余部分。此外,您可以使用多态性来允许单个处理程序处理多个消息类型(在您的例子中是ForwardHandler)

下面是一个实现的快速示例

首先,信息类型:

public abstract class BaseMessage { ... } // base class inherited by every message
public abstract class ForwardableMessage : BaseMessage { ... } // base class for message that should only be forwarded
public class MessageOfTypeA : BaseMessage { ... } // a message of type A (which is not forwardable)
public class MessageOfTypeB : ForwardableMessage { ... } // a message of type B (which is forwardable)
public class MessageOfTypeC : ForwardableMessage { ... } // a message of type C (which is forwardable)
(请注意,在这种情况下,为可转发消息使用接口可能更灵活,我对
public static class MessageHandlersProvider
{
    IEnumerable<MessageHandler> handlers = new List<MessageHandler>()
    {
        new MessageOfTypeAHandler(),
        new MessageForwarderHandler()
    }

    public static void HandleMessage(BaseMessage msg)
    {
        foreach (MessageHandler handler in handlers)
        {
            if (handler.CanHandle(msg))
            {
                handler.Handle(msg);
                // you may stop once you have found a handler that can handle or you might consider that multiple handlers can be applied to the same message
            }
        }
    }
}