11
votes

Représentant une énumération héritière

J'ai un ensemble de valeurs d'énumération (les codes d'erreur doivent être précis). Le code est un entier de 16 bits non signé. Je cherche une structure de données pouvant représenter une telle énumération. Une question similaire a été posée ici: Quel est le meilleur modèle C # pour la mise en œuvre d'une hiérarchie avec un énumé? . Mais cette hiérarchie est plus profonde.

Valeurs d'énumération des échantillons b> p> xxx pré>


Utiliser case B>
Lorsque l'utilisateur fournit un code, l'interface utilisateur doit afficher la signification équivalente du code avec la hiérarchie. de
Par exemple, si l'utilisateur fournit une valeur 0x2121 code>, l'interface utilisateur doit afficher court-circuit à la terre dans la phase 1 dans la couche d'entrée du périphérique code>. La meilleure façon de représenter cela consiste à utiliser une notation hiérarchique: Courant: DeviceInputSide: ShortAearth: ShortAearthinphase1 Code>. P>


Approches concurrentes b>

J'ai trois approches concurrentes pour représenter l'énumération: p>

  1. Créez une énumération à chaque niveau de la hiérarchie. Ensuite, utilisez une classe de contrôleur pour résoudre le nom. LI>
  2. stocker les valeurs d'énumération dans un XML et utilisez LINQ pour générer la signification du code. LI>
  3. stockez les valeurs d'énumération dans un XML. Pendant le démarrage de l'application. Créez une instance Singleton pour récupérer le sens. L'instance contient un dictionnaire peuplé avec les valeurs du XML. li> ol>


    Approche 1 B>
    Les énumérations: p> xxx pré>

    le contrôleur: p> xxx pré>



    Approche 2 B>
    Le XML pour stocker les valeurs d'énumération ressemble à ceci p> xxx pré>

    Et la méthode utilisée pour interroger les codes est la suivante: p> xxx pré>


    Approche 3 B>
    Le XML pour stocker les valeurs d'énumération est la même que dans l'approche 2 b>. Le dictionnaire est peuplé à partir du xml code> par getchildren () code>. p> xxx pré>

    Les significations sont récupérées à l'aide de gethierarchicalmaning () code>: p> xxx pré>

    Warncodevalue Code> Classe: P>

    class WarnCodeValue
    {
        public string Meaning
        { get; set; }
    
        public Dictionary<int, WarnCodeValue> ChildNodes { get; set; }
    }
    


7 commentaires

@DYPPL, les valeurs sont un ensemble de valeurs de code constant (UINT16). J'utilise Enum comme je dois associer chaque code avec sa signification.


S'inspirant de l'approche d'arborescence suggéré par @paolo, la troisième approche (extraction du dictionnaire XML + du sens) a été ajoutée ci-dessus.


J'ai décidé d'aller avec l'approche 3, car il offre une performance améliorée lors de la génération de sens tout en conservant la flexibilité et la hiérarchie du XML .


@Devendra Je pense que vous avez fait le meilleur choix. XML ne va pas presque autant d'amour que c'était il y a 10 ans, mais la seule chose que je pense qu'il est inégalée est la possibilité d'exprimer une structure de données hiérarchique, comme dans ce cas. Seulement une suggestion de plus: je concaténerais les significations de chaque noeud dans GetChildren, lors de la collecte du dictionnaire (qui ne se produise qu'une seule fois au début) plutôt que de la interroger quatre fois à chaque fois que vous recherchez un code.


@paolo, excellente idée! J'ai posté l'approche modifiée 3 code comme réponse. Plutôt que de modifier le , j'ai ajouté une autre propriété concaténatedManing .


@Devendra D. Chavan, allez-vous toujours utiliser un code d'erreur de juste 0x2000 ? Cela me rappelle les codes d'état HTTP et SMTP, 4xx est une erreur client, 3xx est la redirection, etc.


@Chris Haas, les codes d'avertissement sont valides et peuvent survenir dans un scénario. Les codes sont tels que définis dans la spécification, j'ai donc besoin de prendre en charge tous les codes.


4 Réponses :


2
votes

Vous pouvez utiliser FlagsAttribute . Par exemple, vous pouvez faire quelque chose comme ceci: xxx pré>

Vous pouvez le tester comme ceci: p>

int[] testVals = {0x0000, 0x2000, 0x2130, 0x2122, 0x2121, 0x2131};

foreach(var val in testVals)
{
   Console.WriteLine( "{0,4:X} - {1}",
      val, ( (WarnCodes)val ).ToString( ) );
}


10 commentaires

@paolo, cette solution fonctionnera au cas où les énumérations sont distinctes. Dans mon cas, le sens d'une énumération est relatif. Par exemple, inphase1 est présent dans les deux shortcircuit et court-mesure . Mais c'est la signification est déterminée par son parent ( shortciruit ou court-mesure ). Dans une énumération, les valeurs ne peuvent pas être répétées, votre solution ne résoudra pas dans le problème.


@Devendra, FlagSaTribute tourne votre énorme dans un masque bitmask, donc shortciruit -> inphase1 sera correctement associé à 0x__31 tandis que ShortAearth -> Inphase1 sera associé à 0x__21 comme vous l'avez demandé. Avez-vous essayé le code de test que j'ai fourni? Je l'ai étendu à plus de cas, à montrer mieux comment cela fonctionne.


@paolo, j'ai essayé le code que vous avez fourni. Mais le problème est que les codes d'avertissement sont sur plusieurs champs (c'est-à-dire actuellement, tension, etc.), alors que actuel = 0x2000 , il y a une valeur tension = 0x3000 . Donc, dans votre code 0x3122 donnera la signification que inPhase2, shortAearth, périphériqueInputSide, tension . Cela n'a pas de sens (la tension ne peut pas être raccourcie). La valeur d'énumération réelle de 0x3122 est sous-tension du secteur dans la phase L2 .


@Devendra - Je vous suggère de simples utiliser votre approche XML. Bien que l'approche de Paolo soit correcte, cela ne satisfera clairement pas votre problème, et honnêtement, une énumération ne serait pas une bonne méthode pour faire ce que vous faites. Vous avez également utilisé la même valeur pour trois phases différentes dans la même catégorie qui n'a aucun sens.


@Ramhound, même l'approche XML expose le XML à l'utilisateur. En effet, tout utilisateur pourrait bricoler avec le XML faisant fonction de l'application de manière inattendue. De plus, d'un point de vue de la performance, je ne suis pas sûr que cette approche est meilleure.


@Ramhound, les 3 phases différentes ont des valeurs différentes. C'était une faute de frappe. J'ai édité la question de refléter la correction.


@Devendra: Je ferais comme Ramhound suggère et utilise le XML pour représenter votre hiérarchie. Vous pouvez coder le code XML dans une chaîne (si vous êtes préoccupé par un utilisateur altérant les valeurs d'un fichier) et vous pouvez pré-charger tous les codes et les valeurs du XML à un dictionnaire pour améliorer la performance de recherche.


@paolo, l'approche XML impliquera toujours la lecture du XML au début de l'exécution de l'application, ce qui conduit au même problème de corruption de données. Bien que l'approche dictionnaire entraînera néanmoins une amélioration de la performance.


Un (code> Dictionnaire serait une meilleure approche (pour maintenir la hiérarchie tout en améliorant les performances) plutôt que d'utiliser un dictionnaire simple .


@Devendra: J'ai ajouté une autre réponse avec une implémentation basée sur des arbres de votre hiérarchie



5
votes

considérer en utilisant des classes au lieu d'ENUMS, vous utilisez ensuite un singleton pour chaque valeur et peut utiliser le système de type pour créer un arbre, y compris les méthodes virtuelles pour produire une erreur TXT, etc. (Ceux-ci peut parfois être une bonne option , mais peut également vous amener à beaucoup de problèmes s'il ne correspond pas bien)


1 commentaires

L'approche de la classe Singleton impliquera la création d'un type à chaque niveau de la hiérarchie. Ai-je raison? Vous avez mentionné que vous conduit à beaucoup de problèmes si cela ne convient pas bien , pouvez-vous élaborer à ce sujet?



1
votes

Deuxième tentative ... Vous pouvez implémenter votre propre structure d'arborescence où chaque nœud dispose d'une représentation hexadécimale à une seule chiffre et d'un code tel que 0x2121 représente une branche de l'arborescence: xxx pré>

SO, Pour lire ce que 0x2121 signifie, nous suivons la branche correspondante de l'arborescence et (pour chaque nœud), nous lisons le message qu'il contient. P>

Voici une implémentation rapide et sale de l'arborescence: P>

//search meaning of path
root.getMessagesByPath(0x2122)


3 commentaires

C'est une excellente mise en œuvre de l'approche de l'arborescence pour stocker les valeurs. Mais comme vous l'avez souligné, la population est désordonnée et je ne suis pas sûr de pouvoir écrire ce type de code pour renseigner tous les nœuds (il y a environ 100 nœuds!).


@Devendra: Vous n'êtes pas facile à faire s'il vous plait, n'est-ce pas? :) J'ai ajouté une méthode AddBranch à remplir l'arbre peu plus douloureux que d'écrire l'énum ou le XML.


+1, j'ai implémenté l'approche arborescence à l'aide d'un dictionnaire (approche 3). Merci pour l'inspiration. :). De toute façon améliorations sont les bienvenues.



0
votes

a constaté qu'une version modifiée de approche 3 B> est la plus adaptée. Merci à @paolo B> pour m'aider à proposer la réponse.

Approche modifiée 3 B>

Le XML code> contenant les codes: xxx pré>


Le warncodevalue code> classe: p> xxx pré>



La classe code> singleton code> de processeur (pour récupérer la signification d'un code): p> xxx pré>



Utilisation B> P>

string concatenatedMeaning = WarnCodeProcessor.Instance.GetConcatenatedMeaning(0x2121);


1 commentaires

J'avais reçu une suggestion de plus, que la signification concaténée de tous les nœuds peut être placée dans un seul niveau Dictionnaire Dictionnaire où la clé est le code hexadécimal et la valeur est la signification concaténée . Et cela pourrait être utilisé par getMeaning () . Ce dictionnaire doit être créé initialement (lors de l'instanciation singleton).