C# 我怎样才能做出一个“回答”;“摘要”;.NET类库中的枚举?
我正在制作一个服务器库,其中数据包关联由enum完成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,
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,以便客户端可以为符号指定常量值
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;
}
}