2009-09-01 6 views
1

Est-il possible de récupérer par programmation tout le cas d'un commutateur? Je n'ai aucune idée, peut-être par IL mais pas sûr comment faire ...C# itérer sur les cas de commutation

En fait mon problème global est le suivant: J'ai eu un cas de siwtch avec la chaîne comme nom de propriété. La méthode est très importante et une régression n'est pas autorisée. Je ne veux pas qu'un refactoring brise ceci, donc je veux une méthode pour tester que toutes les chaînes de cas sont en fait de vraies propriétés de mes objets. (NB: la valeur par défaut renvoie quelque chose donc je ne peux pas lancer un exceptino pour une valeur invalide refactorisée).

+0

Juste curieux: avez-vous l'intention d'exécuter cette vérification dans le cadre de votre processus de construction? –

+0

Non, je voulais l'ajouter au constructeur statique de la classe ou l'appeler explicitement, mais je peux imaginer le faire pendant le processus de construction. – Toto

Répondre

2

Il existe des moyens d'éviter d'utiliser des noms de propriété en tant que chaîne directement dans votre code. J'ai posté un extrait de code here.

Ensuite, au lieu d'utiliser une instruction switch, mettre en œuvre quelque chose comme ceci:

private IDictionary<string, Action> _actions; 

public void RegisterAction(string propertyName, Action action) 
{ 
    _actions.Add(propertyName, action); 
} 

public void DoSomething(string propertyName) 
{ 
    _actions[propertyName](); 
} 

Lorsque vous appelez les deux méthodes, assurez-vous que vous utilisez la classe membre de l'extrait de code (voir le lien) au lieu d'utiliser les noms de propriété directement. Vous pouvez donc vous assurer que votre code est anti-refactoring, car il ne contient aucune "chaîne magique".

Cordialement

+0

Enfin, utilisé le code affiché sur le poste lié et le dictionnaire comme suggéré, thx! – Toto

1

Obtenir les valeurs dans un commutateur ne serait pas trivial ...

Si vous utilisez un ENUM dans le commutateur au lieu de chaînes, vous pouvez facilement obtenir les valeurs de l'ENUM en utilisant Enum.GetValues.

2

Dans IL, une instruction switch compile à quelque chose comme ceci:

// ... 
L_000c: ldloc.1 
L_000d: ldstr "case1" 
L_0012: call bool [mscorlib]System.String::op_Equality(string, string) 
L_0017: brtrue.s L_0035 
L_0019: ldloc.1 
L_001a: ldstr "case2" 
L_001f: call bool [mscorlib]System.String::op_Equality(string, string) 
L_0024: brtrue.s L_0042 
L_0026: ldloc.1 
L_0027: ldstr "case3" 
L_002c: call bool [mscorlib]System.String::op_Equality(string, string) 
L_0031: brtrue.s L_004f 
// ... 

Ce serait une bonne quantité de travail à écrire du code qui pourrait analyser cela correctement dans tous les cas. La seule façon que je peux voir pour tester ceci est de couvrir réellement tous les cas et s'assurer que vous ne vous retrouviez pas avec un PropertyInfo nul. Si le code avec lequel vous travaillez est très important et ne peut pas échouer, il est probablement très dangereux d'utiliser la réflexion dans tous les cas. Pouvez-vous passer à une conception plus sécurisée?

+0

Et si le switch devient trop grand, le compilateur C# générera une hashtable comme implémentation du switch ... Pas très sympathique IL en effet :) –

+0

Au contraire, si le switch n'est pas petit c'est un jeu d'enfant d'obtenir la hashtable - Voir ma réponse ci-dessous. –

+0

Bien sûr, je ne pensais pas que ce serait facile de le faire. En fait le code peut lancer une exception, je ne veux juste pas qu'il soit correct avec une chaîne invalide comme propriété. – Toto

0

Écrivez un script en AWK ou Perl ou autre pour vérifier la source elle-même, et exécutez-le avant chaque génération.

Questions connexes