Question

Le titre dit à peu près tout. Lorsque je réfléchis dans mes classes, la méthode MemberInfo.GetCustomAttributes () conservera-t-elle l'ordre des attributs d'un membre, ou pas? La documentation officielle ne dit rien dans un sens ou dans l'autre.

Au cas où vous vous demanderiez pourquoi j'en aurais besoin, voici l'explication complète. Elle est longue et inutile pour la question telle qu'elle est posée à présent, mais quelqu'un peut peut-être proposer une solution alternative au problème majeur, qui ne nécessite pas de s'appuyer sur l'ordre de énumération des attributs.

J'essaie de créer un cadre flexible pour une application (ASP.NET) dont la durée de vie devrait être assez longue. Au fil du parcours, il gagnera de nombreux formulaires qui devront être accessibles à partir du menu. Pour faciliter la vie des développeurs, j’ai créé un MenuItemAttribute que vous pouvez appliquer à la classe d’un formulaire. Cet attribut a une quantité illimitée de paramètres de chaîne dans son constructeur, ce qui permet au développeur de spécifier l'emplacement exact du formulaire dans le menu. Un exemple d'utilisation typique serait quelque chose comme [MenuItem("Company", "Clients", "Orders")] qui voudrait alors dire que le menu devrait avoir un élément & "Société &"; sous lequel il y aurait un élément " Clients " sous lequel il y aurait un élément " Orders " - qui ouvrirait alors le formulaire. Un seul formulaire peut avoir plusieurs de ces attributs si nécessaire - il sera alors accessible depuis plusieurs endroits du menu.

Évidemment, tout le menu est construit à l'exécution en énumérant toutes les classes de mes assemblages et en recherchant cet attribut. Cependant, j'ai récemment reçu une demande pour que les éléments de menu soient triés d'une manière prédéfinie. Les formulaires ayant des fonctionnalités connexes doivent être côte à côte dans le menu. Notez qu'il ne s'agit PAS d'un tri alphabétique, mais d'un ordre prédéfini spécifié par les développeurs.

Cela pose alors le problème - comment puis-je spécifier l'ordre dans ces attributs? Etant donné qu'un MenuItemOrderHintAttribute décrit toute une hiérarchie, la spécification de la commande doit également inclure les numéros de commande pour l'ensemble (ou au moins une partie) de la hiérarchie. Un numéro d'ordre uniquement pour le niveau inférieur de la hiérarchie n'est pas suffisant.

Je pourrais créer un autre attribut - <=>, mais cela poserait alors des problèmes avec les cas où il y a plus d'un <=>. D'où la question initiale.

Je pourrais aussi étendre le <=> pour prendre deux tableaux ou un tableau de paires, mais cela compliquerait beaucoup la syntaxe. La dernière idée est que je pourrais faire en sorte que les chaînes aient un format spécial, mais ce serait plutôt compliqué à mon humble avis.

OK, j'ai une autre idée. Utilisons la commande suggérée par Jon Skeet. Cela permettra de spécifier l'ordre du dernier niveau de la hiérarchie, pas celui des niveaux supérieurs. Mais je pourrais modifier l'attribut pour qu'il s'applique non seulement aux classes, mais également à l'assembly lui-même. Dans ce cas, l'élément de menu n'aurait pas de formulaire associé. Au niveau de l’assemblage, ces attributs pourraient ensuite être utilisés pour spécifier l’ordre entre les niveaux supérieurs de la hiérarchie.

C’est donc un compromis entre un système de menus centralisé et décentralisé. Des idées pour lesquelles cela serait une mauvaise idée?

Était-ce utile?

La solution

Je mettrais une seule valeur supplémentaire (facultative) dans le constructeur MenuItemAttribute, qui est & "order &"; ou " priorité "

[MenuItem(0, "Company", "Clients", "Orders")]
[MenuItem(1, "Foo", "Bar", "Baz")]

Je ne dis pas que ce serait joli, mais cela vous permettrait effectivement de spécifier l'ordre.

Autres conseils

Il n’est pas garanti que absolument l’ordre lexical des éléments d’un fichier soit conservé dans les assemblages CIL résultants, ni respecté dans les résultats renvoyés par Reflection. Cette commande n'est même pas garantie d'être identique pour les appels répétés dans le même domaine d'application!

Notez que les États-Unis ont cassé cet ordre dans d'autres parties de la réflexion dans le passé (notant que cela leur causait des problèmes pour certains de leurs codes), donc même si cela fonctionne actuellement, il n'y a rien arrêter cette rupture à l’avenir ou sur différentes plates-formes.

Pensez à modifier votre modèle d'attribut pour permettre l'expression directe des informations sémantiques plutôt que de vous fier à l'ordre.

Malheureusement non, vous ne pouvez pas garantir que l'ordre sera le même que celui dans lequel vous l'avez spécifié.

Modifier: une solution de contournement

Clause de non-responsabilité: je m'excuse à l'avance si je comprends mal votre problème ultime.

Il semblerait que vous deviez pouvoir passer n nombre de chaînes à MenuItemAttribute et laisser LinkedList<String> conserver l'ordre de ces chaînes telles qu'elles ont été entrées par le développeur dans le constructeur d'attributs.

Voici une solution possible:

Demander à params String[] d'utiliser un <=> à conserver son état. Ensuite, vous pouvez itérer le <=> dans votre constructeur et les ajouter au <=> qui maintiendrait l'ordre.

Il me semble que votre problème provient du fait que les formulaires spécifient leur emplacement dans votre menu, ce qui signifie que vous essayez de créer un menu en combinant tous les formulaires d'un assemblage. Cela peut être plus simple si vous spécifiez la structure du menu séparément de tout formulaire et si vous résolvez les formulaires à partir de diverses propriétés / attributs définis dans la classe correspondant à un élément de menu.

par exemple

public class MenuItem
{
    string Text { get; }
    Type FormType { get; }
    ICollection<MenuItem> SubItems { get; }
}

Puis, lorsqu'un élément de menu est sélectionné, résolvez le formulaire et affichez-le. Cette approche a l’inconvénient que tout nouveau formulaire nécessite une modification du code spécifiant la structure du menu ainsi que le formulaire lui-même, mais ce sera tout à fait mineur ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top