C# 实施一套「;福斯;其中有一个子集为;酒吧;在C中#
我正在编写一个服务器来处理从客户端到主机的不同类型的消息。消息的内容和长度各不相同,前面会有一个标识符,以标识消息的类型。一些消息(例如,类型A、B和C)应该在机器之间转发。其他(例如类型D、E和F)需要服务器执行特定操作:即,它们不只是转发 (注意:两端的客户端需要区分A、B和C,但服务器只需要知道如何转发这些消息。服务器和客户端都需要能够区分D、E和F。) 我试图找到一个很好的面向对象的范例,用于表示消息的“类型”。因此,为了澄清这一点,假设服务器收到一条标记为“Type B”的消息,它只需将该消息转发给相应的客户端即可。但是,如果它收到标记为“F型”的消息,它将采取不同的、特定的操作。那么,如何在代码中表示“类型” 我想要实现的理想解决方案是这样的;枚举“类型”,其中命令的某个子集属于“可转发”类型。显然这是不可能的,所以我想到了一个静态类,Forwardable,它继承自一个静态基类Type。同样,不可能。接口是可能的,但我真的不想为了解释类型而实例化实例 让服务器解析消息的最直接方法如下: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”的消息,它只需
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);
考虑到你的问题,我会做以下几点:
- 对每条消息使用对象表示
- 使用类似的模式根据消息类型处理消息
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
}
}
}
}