C# 我怎样才能做出一个“回答”;“摘要”;.NET类库中的枚举?

C# 我怎样才能做出一个“回答”;“摘要”;.NET类库中的枚举?,c#,enums,abstract,C#,Enums,Abstract,我正在制作一个服务器库,其中数据包关联由enum完成 public enum ServerOperationCode : byte { LoginResponse = 0x00, SelectionResponse = 0x01, BlahBlahResponse = 0x02 } public enum ClientOperationCode : byte { LoginRequest = 0x00, SelectionRequest = 0x01,

我正在制作一个服务器库,其中数据包关联由enum完成

public enum ServerOperationCode : byte
{
    LoginResponse = 0x00,
    SelectionResponse = 0x01,
    BlahBlahResponse = 0x02
}

public enum ClientOperationCode : byte
{
    LoginRequest = 0x00,
    SelectionRequest = 0x01,
    BlahBlahRequest = 0x02
}
当您在自己的项目中工作时,这很好——您可以比较返回的枚举成员(即
if(packet.OperationCode==ClientOperationCode.LoginRequest)
)。但是,由于这是一个类库,用户必须定义自己的枚举


因此,我有两个枚举要添加为“抽象”-ServerOperationCode和ClientOperationCode。我知道用C#实现抽象枚举是不可能的。我该怎么做呢?

如果您想说您想要一个可由库的客户端扩展的枚举,请查看我关于这个主题的CodeProject文章

请注意,在我的库中,Symbol自动为“枚举值”选择ID号,因为它是为在单个程序中使用而设计的,而不是用于在网络上交换值。不过,也许可以根据您的喜好更改Symbol.cs,以便客户端可以为符号指定常量值

  • 为LoginResponse、SelectionResponse等创建枚举,但不指定值

  • 让ServerOperationCode和ClientOperationCode实现一个函数,在给定整数字节码的情况下,该函数从枚举中返回适当的值

  • 例如:

    public enum OperationCode
    {
     LoginResponse,
     SelectionResponse,
     BlahBlahResponse
    }
    
    public interface IOperationCodeTranslator {
     public OperationCode GetOperationCode(byte inputcode);
     }
    
    public class ServerOperationCode : IOperationCodeTranslator
    {
      public OperationCode GetOperationCode(byte inputcode) {
        switch(inputcode) {
           case 0x00: return OperationCode.LoginResponse;
          [...]
        } 
    }
    
    警告:由于接口不能定义静态函数,ServerOperationCode和ClientOperationCode只能在所述函数是实例函数的情况下实现公共接口。如果不需要实现公共接口,GetOperationCode可以是一个静态函数


    (对任何C#混乱表示歉意,这不是我的第一语言…

    如果您的客户端和服务器应用程序之间共享了一个数据库,那么查找表可能会有所帮助;表结构只包含一个整数值(ID)和一个字符串(名称),该表可以由应用程序的任意一方(客户端或服务器)填写,也可以由另一方读取。您可以将这些表(在代码中)缓存到字典中,以便快速查找


    您也可以在app.config文件中实现相同的功能;强制库的用户在app.config文件中设置这些值,库可以轻松访问这些值。

    需要时,我喜欢在类上使用静态实例。它允许您拥有一些默认值,但也允许通过通常的继承和接口实现方式进行扩展:

        public abstract class OperationCode
        {
            public byte Code { get; private set; }
            public OperationCode(byte code)
            {
                Code = code;
            }
        }
    
        public class ServerOperationCode : OperationCode
        {
            public static ServerOperationCode LoginResponse = new ServerOperationCode(0x00);
            public static ServerOperationCode SelectionResponse = new ServerOperationCode(0x01);
            public static ServerOperationCode BlahBlahResponse = new ServerOperationCode(0x02);
    
            public ServerOperationCode(byte code) : base(code) { }
        }
    
        public class ClientOperationCode : OperationCode
        {
            public static ClientOperationCode LoginRequest = new ClientOperationCode(0x00);
            public static ClientOperationCode SelectionRequest = new ClientOperationCode(0x01);
            public static ClientOperationCode BlahBlahRequest = new ClientOperationCode(0x02);
    
            public ClientOperationCode(byte code) : base(code) { }
        }
    
    假设
    packet.OperationCode
    返回一个字节,您可能需要为字节实现==运算符。将此代码放入抽象OperationCode类中

    public static bool operator ==(OperationCode a, OperationCode b)
    {
      return a.Code == b.Code;
    }
    
    public static bool operator !=(OperationCode a, OperationCode b)
    {
      return !(a == b);
    }
    
    这将允许您进行与所示相同的检查:

    if (packet.OperationCode == ClientOperationCode.LoginRequest)

    不久前,我编写了一个具有类似场景的消息交换库,并决定使用泛型传递用户定义的枚举。这方面的主要问题是不能将泛型限制为仅枚举类型,而只能说while t:struct。有人可能会用其他一些基元类型实例化您的类型(不过,如果int都是唯一值,那么使用int仍然可以起作用。如果它们不是唯一值,字典将抛出异常。您可以使用反射添加一些额外的检查,以确保通过枚举

    public abstract class DefaultMessageHandler<T> : IMessageHandler<T> where T : struct {
        public delegate void MessageHandlerDelegate(IMessage<T> message, IConnection connnection);
    
        private readonly IDictionary<T, MessageHandlerDelegate> messageHandlerDictionary = 
            new Dictionary<T, MessageHandlerDelegate>();
    
        protected void RegisterMessageHandler(T messageType, MessageHandlerDelegate handler) {
            if (this.messageHandlerDictionary.ContainsKey(messageType)) 
                return;
            else this.messageHandlerDictionary.Add(messageType, handler);
        }
    
        protected void UnregisterMessageHandler(T messageType) {
            if (this.messageHandlerDictionary.ContainsKey(messageType))
                this.messageHandlerDictionary.Remove(messageType);
        }
    
        protected virtual void HandleUnregisteredMessage(IMessage<T> message, IConnection connection) {
        }
    
        void IMessageHandler<T>.HandleMessage(IMessage<T> message, IConnection connection) {
            if (this.messageHandlerDictionary.ContainsKey(message.MessageType))
                this.messageHandlerDictionary[message.MessageType].Invoke(message, connection);
            else HandleUnregisteredMessage(message, connection);
        }
    }
    
    公共抽象类DefaultMessageHandler:IMessageHandler其中T:struct{
    公共委托void MessageHandlerDelegate(IMessage message,IConnection connection);
    专用只读IDictionary messageHandlerDictionary=
    新字典();
    受保护的无效注册表MessageHandler(T messageType、MessageHandlerDelegate handler){
    if(this.messageHandlerDictionary.ContainsKey(messageType))
    返回;
    否则这个.messageHandlerDictionary.Add(messageType,handler);
    }
    受保护的void UnregisterMessageHandler(T messageType){
    if(this.messageHandlerDictionary.ContainsKey(messageType))
    this.messageHandlerDictionary.Remove(messageType);
    }
    受保护的虚拟void HandleUnregisteredMessage(IMessage消息、IConnection连接){
    }
    void IMessageHandler.HandleMessage(IMessage消息,IConnection连接){
    if(this.messageHandlerDictionary.ContainsKey(message.MessageType))
    this.messageHandlerDictionary[message.MessageType].Invoke(消息,连接);
    else HandleUnregisteredMessage(消息、连接);
    }
    }
    
    根据您的示例场景,您只需将其子类化如下

    public sealed class ServerOperationHandler : DefaultMessageHandler<ServerOperationCode> {
        public ServerOperationHandler() {
            this.RegisterMessageHandler(ServerOperationCode.LoginResponse, this.HandleLoginResponse);
            this.RegisterMessageHandler(ServerOperationCode.SelectionResponse, this.HandleSelectionResponse);
        }
    
        private void HandleLoginResponse(IMessage<ServerOperationCode> message, IConnection connection) {
            //TODO
        }
    
        private void HandleSelectionResponse(IMessage<ServerOperationCode> message, IConnection connection) {
            //TODO
        }
    }
    
    公共密封类ServerOperationHandler:DefaultMessageHandler{
    公共服务器操作处理程序(){
    this.RegisterMessageHandler(ServerOperationCode.LoginResponse,this.HandleLoginResponse);
    this.RegisterMessageHandler(ServerOperationCode.SelectionResponse,this.HandleSelectionResponse);
    }
    私有无效HandleLoginResponse(IMessage消息、IConnection连接){
    //待办事项
    }
    私有void HandleSelectionResponse(IMessage消息、IConnection连接){
    //待办事项
    }
    }
    
    为什么每个人都认为枚举不能抽象

    类System.Enum是枚举的抽象

    可以将任何枚举值指定给枚举,也可以将其强制转换回原始枚举或使用名称或值

    例如:

    这段代码来自我的一个控件库中使用的一个动态属性集合。我允许通过枚举值创建和访问属性,以使其稍快一些,并减少人为错误

        /// <summary>
        /// creates a new trigger property.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        protected virtual TriggerProperty<T> Create<T>(T value, Enum name)
        {
            var pt = new TriggerProperty<T>(value, OnPropertyChanged, Enum.GetName(name.GetType(), name));
            _properties[name.GetHashCode()] = pt;
            return pt;
        }
    

    使用静态字典和虚拟方法来检索继承类中的静态字典怎么样

    对于您的案例,如下所示:

        public abstract class Operation
        {
            protected abstract Dictionary<string, int> getCodeTable();
            public int returnOpCode(string request){ return getCodeTable()[request]; }
        }
        public class ServerOperation : Operation
        {
            Dictionary<string, int> serverOpCodeTable = new Dictionary<string, int>()
            {
                {"LoginResponse", 0x00,},
                {"SelectionResponse", 0x01},
                {"BlahBlahResponse", 0x02}
            };
            protected override Dictionary<string, int> getCodeTable()
            {
                return serverOpCodeTable;
            }
    
        }
        public class ClientOperation : Operation
        {
            Dictionary<string, int> cilentOpCodeTable = new Dictionary<string, int>()
            {
                {"LoginResponse", 0x00,},
                {"SelectionResponse", 0x01},
                {"BlahBlahResponse", 0x02}
            };
            protected override Dictionary<string, int> getCodeTable()
            {
                return cilentOpCodeTable;
            }
        }
    
    公共抽象类操作
    {
    受保护的抽象字典getCodeTable();
    public int returnOpCode(字符串请求){return getCodeTable()[request];}
    }
    公共类服务器操作:操作
    {
    
        public abstract class Operation
        {
            protected abstract Dictionary<string, int> getCodeTable();
            public int returnOpCode(string request){ return getCodeTable()[request]; }
        }
        public class ServerOperation : Operation
        {
            Dictionary<string, int> serverOpCodeTable = new Dictionary<string, int>()
            {
                {"LoginResponse", 0x00,},
                {"SelectionResponse", 0x01},
                {"BlahBlahResponse", 0x02}
            };
            protected override Dictionary<string, int> getCodeTable()
            {
                return serverOpCodeTable;
            }
    
        }
        public class ClientOperation : Operation
        {
            Dictionary<string, int> cilentOpCodeTable = new Dictionary<string, int>()
            {
                {"LoginResponse", 0x00,},
                {"SelectionResponse", 0x01},
                {"BlahBlahResponse", 0x02}
            };
            protected override Dictionary<string, int> getCodeTable()
            {
                return cilentOpCodeTable;
            }
        }