12
votes

Comment puis-je faire un "abstrait" enum dans une bibliothèque de classe .NET?

Je fais une bibliothèque de serveur dans laquelle l'association de paquets est effectuée par ENUM.

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

public enum ClientOperationCode : byte
{
    LoginRequest = 0x00,
    SelectionRequest = 0x01,
    BlahBlahRequest = 0x02
}


2 commentaires

Je ne peux pas comprendre ce que vous essayez ici. Vous voulez que vos codes soient réels .NET Types afin que votre client reçoit le type de contrôle, mais je ne veux pas que le client voie les valeurs? Qu'essayez-vous de faire que le client ajoutant une référence à votre bibliothèque ne résout pas?


Je pense que j'essaie réellement de faire une bibliothèque dans laquelle des objets statiques peuvent être étendus, ce qui est impossible. Par exemple, une bibliothèque dans laquelle vous pouvez remplacer ou mettre en œuvre "server.start", mais ce n'est pas tout à fait possible. Je pourrais y aller par des événements, cependant. Je vais voir ce que je peux faire, merci pour toutes les réponses, je vais les essayer.


7 Réponses :


0
votes

Si vous voulez dire que vous souhaitez que vous souhaitiez une énumération pouvant être prolongée par des clients de la bibliothèque, consultez mon article de codeProject sur le sujet, symboles comme extensible Enums .

Notez que dans ma bibliothèque, le symbole choisit automatiquement les numéros d'identification pour les "valeurs d'enum", car il est conçu pour une utilisation dans un programme unique plutôt que pour échanger des valeurs sur un réseau. Peut-être qu'il serait toutefois possible de modifier le symbole.cs à votre goût afin que les clients puissent attribuer des valeurs constantes aux symboles.


0 commentaires

0
votes
  1. Créez une énumération pour loginResponse, SelectionResponse, etc., mais ne spécifiez pas les valeurs. p> li>

  2. avoir ServerOrcolationCode et CLIDEOPERATIONCODE Mettre en place une fonction qui, étant donné un bytecode entier, renvoie la valeur appropriée de votre énum. p> li>

    Exemple: P>

    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;
          [...]
        } 
    }
    

0 commentaires

0
votes

S'il y a une base de données partagée entre votre demande de client et de votre serveur, les tables de recherche peuvent aider; La structure de la table contient simplement une valeur entière (ID) et une chaîne (nom), ce tableau peut être rempli de chaque côté de votre application (le client ou le serveur) et lire par l'autre. Vous pouvez cacher ces table (dans votre code) dans un dictionnaire pour une recherche rapide.

Vous pouvez également implémenter la même chose dans le fichier app.config; forcer l'utilisateur de votre bibliothèque à définir ces valeurs dans le fichier app.config que votre bibliothèque peut accéder facilement.


0 commentaires

14
votes

J'aime utiliser des instances statiques sur mes cours quand j'ai besoin de le faire. Il vous permet d'avoir des valeurs par défaut, mais le permet également d'être extensible par le moyen habituel des implémentations d'héritage et d'interface: xxx pré>

supposant paquet.OperationCode code> retourner un octet, Vous devrez probablement mettre en œuvre un opérateur == pour l'octet. Placez ce code dans votre classe de codes abstrait. p> xxx pré>

Ceci vous permettra d'avoir le même chèque que vous l'avez montré: p>

if (packet.OperationCode == ClientOperationCode.LoginRequest)


0 commentaires

0
votes

J'ai écrit une bibliothèque de commutation de messages avec un scénario similaire au dos, et j'ai décidé d'utiliser des génériques pour réussir l'énumé défini par l'utilisateur. Le problème principal avec ceci est que vous ne pouvez pas limiter votre générique à des types d'énumération, mais ne peut que dire que si T: struct. Quelqu'un peut instancier votre type avec un autre type primitif (bien que l'utilisation d'INTS pourrait toujours être fonctionnelle, à condition qu'ils soient toutes des valeurs uniques. Le dictionnaire organisera une exception si ce ne sont pas. Vous pouvez éventuellement ajouter un contrôle supplémentaire à l'aide de la réflexion à la réflexion. Assurez-vous de passer un énumé.

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
    }
}


0 commentaires

8
votes

Pourquoi tout le monde pense que Enums ne peut pas être abstrait?

Le système de classe.Enum est l'abstraction d'une énumération.

Vous pouvez attribuer une valeur d'énumération à un Enum, et vous pouvez le jeter à l'énumération d'origine ou utiliser le nom ou la valeur.

par exemple:

Ce petit extrait de code provient d'une collection de biens dynamiques utilisée dans l'une des mes bibliothèques de contrôle. Je permet aux propriétés de créer et d'accéder via une valeur d'énumération pour le rendre légèrement plus rapide, et moins d'erreur humaine xxx

i utilise énum.getname (type, objet ) Pour obtenir le nom de la valeur d'énumération (pour fournir un nom pour la propriété), et pour les raisons de la vitesse et de la cohérence, j'utilise gethascode () pour renvoyer la valeur entière de l'élément de dénombrement (Le code de hachage pour un int est toujours juste la valeur INT)

Ceci est un exemple de la méthode appelée: xxx


1 commentaires

C'est exactement la réponse dont j'avais besoin ici. J'aimerais pouvoir uppoter cela plus. Cette perspicacité m'a permis de créer un dictionnaire dans une classe de base abstrait qui serait instanciée par diverses sous-classes, chacune avec sa propre définition d'énumération. Parfait!



0
votes

Que diriez-vous d'utiliser un dictionnaire statique et d'une méthode virtuelle pour récupérer les dictionnaires statiques dans les classes héritées?

Comme le suivant pour votre cas: p>

    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;
        }
    }


0 commentaires