Question

Je crée un client de discussion réseau en C # en tant que projet parallèle. En plus des messages texte simples, j'ai également des commandes préfixées par une barre oblique qui peuvent être entrées dans la zone de saisie TextBox. J'ai utilisé une approche modulaire en créant une énumération contenant toutes les commandes, puis en les décorant d'attributs.

Les attributs spécifient quelle commande à préfixe slash peut être entrée pour déclencher la commande, ainsi que tous les alias associés à l'identificateur de commande principal et à l'utilisation de la commande.

Exemple:

public enum CommandType : byte
{
    [PrimaryIdentifier("file"),
     AdditionalIdentifier("f"),
     CommandUsage("[<recipient>] [<filelocation>]")]
    FileTransferInitiation,

    [PrimaryIdentifier("accept"),
     AdditionalIdentifier("a")]
    AcceptFileTransfer,

    // ...
}

Mon problème survient lorsque j'essaie d'autoriser plusieurs alias à la commande principale. J'ai essayé cela de deux manières: en autorisant les doublons de l'attribut AdditionalIdentifier ou en transformant l'argument du constructeur dans AdditionalIdentifier en params string [] .

Avec l'ancien, je l'ai implémenté en décorant la classe d'attributs avec AttributeUsage et en définissant AllowMultiple sur true. Bien que cela permette effectivement de réaliser ce que je recherche, je pense que cela pourrait devenir très bruyant très rapidement d’avoir plusieurs lignes de pseudonymes, en plus des autres attributs.

Ce dernier fonctionne également, cependant, il génère le avertissement du compilateur CS3016 , et indique que cette approche n'est pas conforme à CLS. Cela ne m'empêche évidemment pas de continuer à l'utiliser, mais j'ai appris à toujours traiter les avertissements comme des erreurs.

Ma question est la suivante: dois-je ignorer mes objections avec les doublons et continuer à les utiliser, ou existe-t-il une autre solution qui pourrait être utilisée?

Merci.

Était-ce utile?

La solution

Personnellement, je choisirais l’approche AllowMultiple: je ne pense pas que le "bruit" Cela posera un problème si vous n'avez pas vraiment de nombreux identifiants pour chaque commande. Mais si vous n'aimez pas cela et souhaitez rester conforme à CLS, une autre solution serait de fournir des constructeurs surchargés pour AdditionalIdentifierAttribute:

public AdditionalIdentifierAttribute(string id) { ... }
public AdditionalIdentifierAttribute(string id1, string id2) { ... }
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... }

L'inconvénient est que cela vous limite à un nombre prédéterminé d'identifiants.

Cela dit, la conformité CLS n’est vraiment un élément important à prendre en compte si vous construisez une bibliothèque que d’autres utilisateurs sont susceptibles d’utiliser (et plus précisément dans d’autres langues). Si ce type ou la bibliothèque est interne à votre application, il est raisonnable d'ignorer les avertissements de conformité CLS.

MODIFIER: Si vous y réfléchissez un peu plus, vous avez beaucoup d'attributs dans ces énumérations. Vous voudrez peut-être envisager de créer une classe de commandes abstraite à la place et d'exposer les identifiants, l'utilisation, etc. en tant que propriétés de cette classe; dérivez ensuite des types concrets de commande qui renvoient les valeurs appropriées à partir de ces propriétés. Cela vous permet également potentiellement de déplacer la logique de traitement dans ces objets Command plutôt que d'activer la valeur enum.

Autres conseils

Vous pouvez également utiliser "params string [] aliases". dans le constructeur pour autoriser une liste d'arguments variables:

[AttributeUsage(AttributeTargets.Method)]
class TestAttribute : Attribute
{
    public TestAttribute(params string[] aliases)
    {
        allowedAliases = aliases;
    }

    public string[] allowedAliases { get; set; }

}

Cela vous permettrait de faire:

[Test("test1", "test2", "test3")]
static void Main(string[] args)

Pourquoi ne pas avoir un seul attribut avec plusieurs propriétés? Demandez à la propriété de l'alias de prendre une liste séparée par des virgules. C'est l'approche qu'ils adoptent dans MVC pour des tâches telles que AuthorizeAttribute for Roles. En interne, la propriété analyse la chaîne dans un tableau afin de faciliter son utilisation dans la classe d'attribut, mais vous permet de configurer facilement votre configuration.

public class IdentifierAttribute
{
    public string Name { get; set; }
    public string Usage { get; set; }

    private string[] aliasArray;
    private string aliases;
    public string Aliases
    {
         get { return this.aliases; }
         set
         {
             this.aliases = value;
             this.aliasArray = value.Split(',').Trim();
         }
    }
}

Ensuite, utilisez-le comme:

public enum CommandType : byte
{
     [Identifer( Name = "file", Aliases = "f", Usage = "..." )]
     FileTransferType,

     ...
}

Pourtant, une autre approche consisterait à faire en sorte que l'attribut prenne un tableau de chaînes en tant que paramètre constructeur - de cette façon, le compilateur analysera le tableau pour vous (au détriment d'un peu plus de temps lors de l'application de l'attribut). :

[Identifiers(new string[] {"Bill", "Ben", "Ted"})]

Exemple rapide d'implémentation de & amp; en utilisant une telle technique ressemble à ceci:

using System;
using System.Collections.ObjectModel;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            SomeClass.TellMeAboutYourself();
        }
    }
    public class Identifiers : Attribute
    {
        private string[] names;
        public Identifiers(string[] someNames)
        {
            names = someNames;
        }
        public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } }
    }
    [Identifiers(new string[] {"Bill", "Ben", "Ted"})]
    static class SomeClass
    {
        public static void TellMeAboutYourself()
        {
            Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers));
            foreach (var s in theAttribute.Names)
            {
                Console.WriteLine(s);
            }
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top