2009-09-02 8 views
1

Je suis en train de mettre en place un système pour envoyer des messages entre différentes parties d'un programme que j'écris. Il y a quelques types de messages génériques ainsi que certains spécifiques à chaque partie du programme. Je voudrais éviter la pourriture de la hiérarchie inhérente à la dérivation d'une classe de message de base pour chaque type, donc j'encapsule ce type dans un int ou ushort. Ensuite, je centralise les différents types avec un espace de noms "Messages", et une classe statique avec un tas de constantes. Cependant, je suis tombé sur la question d'avoir à maintenir une liste de numéros uniques pour chaque section différente:Identificateur unique commutable en C#

namespace Messages 
{ 
    public static class Generic 
    { 
     public const Int32 Unknown = 0; 
     public const Int32 Initialize = 1; 
     ... 
     public const Int32 Destroy = 10; 
    } 
} 

Ensuite ailleurs

namespace Messages 
{ 
    public static class Graphics 
    { 
     public const Int32 Unknown = 0; 
     public const Int32 AddGraphic = 11; // <-- ? 
    } 
} 

Ayant cette 11 arbitraire semble difficile, surtout si j'ai plusieurs ceux-ci, le maintien et la mise à jour pour s'assurer qu'il n'y a pas de collisions semble être une douleur. Y a-t-il une solution facile pour s'assurer que chaque référence à ceci est unique? J'ai essayé d'utiliser readonly statique, en les initialisant d'une fonction Unique.ID() dans un constructeur statique, mais si je le fais, je suis incapable de basculer() sur le type Message transmis, comme il est dit "Un type constant est attendu" pour chaque cas.

+0

Quel est le problème avec juste avoir des objets? public static readonly object AddGraphic = nouvel objet(), chacun devient unique (dans le runtime au moins)? – meandmycode

+0

Je ne peux pas basculer en fonction d'une valeur en lecture seule. Je repense mon design de toute façon. – Quantumplation

Répondre

7

Y a-t-il une raison pour laquelle vous n'utilisez pas d'énumérations?

public enum MessageTypes 
{ 
    Unknown, 
    Initialize, 
    ... 
} 

- Edit:

Élaborant sur mon commentaire, tenez compte

enum MessageType 
{ 
    Update, 
    Delete, 
    Destroy 
} 

MessageType t = ...; 

switch(t){ 
    case MessageType.Update: 
     DoUpdate(); 
    } 
} 

Versus:

interface IActionable 
{ 
    void Do(); 
} 


public abstract class ActionableBase : IActionable 
{ 
    // some other things 

    public abstract void Do(); 
} 


public class UpdateAction : ActionableBase 
{ 
    public override void Do() 
    { 
     // Update Code 
    } 
} 

... 

IActionable a = ...; 
a.Do(); 
+0

Une énumération ne me permettrait pas de "partitionner" la déclaration de différents types de message. Switch (message.Type) { case Messages.Generic.Initialize: break; case Messages.Graphics.AddGraphic: pause; } – Quantumplation

+0

(euh, le formatage est sorti bizarre mais je suis sûr que vous avez l'idée.) – Quantumplation

+0

Vous avez dit dans votre message que vous ne vouliez pas une hiérarchie de classes, maintenant vous en voulez une? Pour être honnête, si votre déclaration switch est si grande, je dirais que vous devriez probablement penser à la façon de rendre votre conception plus OO. –

1

Vous pouvez utiliser une plage de numéros pour chaque classe. Définissez un numéro de base pour la classe et ajoutez 0, 1, 2, etc. à ce numéro de base.

1

Si vous voulez les garder numérique est une façon de les diviser en différentes grandeurs:

namespace Messages 
{ 
    public static class Generic 
    { 
     // these messages are 3-figure numbers 
     public const Int32 Unknown = 0; 
     public const Int32 Initialize = 101; 
     ... 
     public const Int32 Destroy = 110; 
    } 

    public static class Graphics 
    { 
     // these messages are 4-figure numbers 
     public const Int32 Unknown = 0; 
     public const Int32 AddGraphic = 1001; // <-- ? 
     // and so on... 
    } 

} 

Ensuite, vous devez juste vous assurer que vous gardez dans les limites pour chaque type de message.

1

Ce n'est pas automatique, mais il peut être un peu plus facile à maintenir puis de copier les valeurs partout:

public enum Generic 
    { 
     Unknown = 0, 
     Initialize = 1, 
     Destroy = 10 
    } 

    public enum Graphics 
    { 
     AddGraphic = Generic.Destroy + 1 
    } 

Ainsi, vous pouvez avoir tous vos énumérations spécifiques commencer par la valeur d'une ENUM précédente définir et les construire comme ça.

Dans vos objets réels, vous pouvez les stocker sous forme d'int et convertir simplement la valeur enum à l'int approprié. Bien qu'il semble que l'héritage soit inévitable dans ce cas, il existe une hiérarchie naturelle dans votre modèle de données.

+0

Pourquoi ne pas ajouter AddGraphic juste une autre option dans l'énumération générique? –

+0

Taylor: Je cherche à décentraliser les types de message, de sorte que les différents systèmes définissent leurs propres types de message. – Quantumplation

+0

@Taylor afin qu'il puisse passer à la fois Generic.Value ou Graphics.Value dans la même méthode et ne pas avoir de valeurs qui se chevauchent (par exemple, Generic.Unknown et Graphics.AddGraphic seraient tous les deux 0) –

0

Je vous suggère de rechercher la différence entre 'command' & 'message', ceci pourrait vous aider à arriver à la conclusion que l'utilisation de nombres magiques \ enums dans les messages est une mauvaise idée.

Idéalement, vous voulez créer des «commandes» qui sont observées et actionnées par les auditeurs ...

HTH

Ollie

0

Si vous avez vraiment, vraiment envie de le faire, vous pouvez créer un Enum privé générique qui contient toutes les valeurs possibles.

Vous pouvez ensuite exposer ces valeurs à travers vos classes séparées en tant que propriétés en lecture seule qui exposent les énumérations en tant qu'Int32 - par ex.

namespace Messages 
{ 
    private enum AllMessageTypes 
    { 
     Update, 
     Delete, 
     Destroy, 
     AddGraphic 
    } 

    public static class Generic 
    { 
     public Int32 Update 
     { 
      get { return (Int32)AllMessageTypes.Update; } 
     } 
     ... 
    } 

    public static class Graphics 
    { 
     public Int32 AddGraphic 
     { 
      get { return (Int32)AllMessageTypes.AddGraphic ; } 
     } 
    } 
} 

Cependant, je vous recommande de revoir votre solution. Cela semble poser des problèmes (comme je suis sûr que les gens vont commenter)

+0

Oui. Je pense que je vais créer l'ID en && ensemble un "SystemID" et un "CommandID" (00010000 && 0001). Autrement dit, si je ne trouve pas une solution remaniée que j'aime. – Quantumplation

Questions connexes