2009-04-06 8 views
2

J'ai les classes suivantes. Pour tester, je voudrais obtenir toutes les permutations possibles de la classe Client. Je sais que le nombre peut être très important, mais ce n'est pas mon problème pour l'instant.Générer toutes les permutations possibles d'une classe

Client: Non (int), nom (string), adresse (objet Adresse)
Adresse: Rue (string), Pays (string), etc.

Pour une propriété de type int, j'ai toujours essayez les trois mêmes valeurs (-1, 0, 1), pour la chaîne (null, string.Empty, "Hello World", etc.). Pour les types de base, cela fonctionne bien. Cependant, pour l'adresse de classe, ceci est différent. En bref, j'essaie d'écrire une méthode assez générique pour prendre n'importe quel type (classe, etc.) et obtenir toutes les permutations possibles (en d'autres termes: public IEnumerable GetPermutations (Type myType)). Avec l'aide de .NET Reflection, cette méthode boucle sur toutes les propriétés définissables.

Est-ce que quelqu'un a une idée de comment faire cela?

Merci

+0

D'où obtenez-vous ces valeurs? avez-vous une liste de valeurs autorisées, par exemple? – Aziz

+0

@Aziz: Il demande une force brute pour chaque valeur possible. – Samuel

+0

Combien de travail avez-vous déjà fait? Quelle est la partie avec laquelle vous rencontrez des problèmes (générer les permutations, stocker les informations d'adresse, utiliser la réflexion, etc ...)? –

Répondre

1

Voici une classe qui peut vous aider à démarrer, même si je ne l'ai pas beaucoup testé. Notez que ceci ne fonctionnera que pour les classes qui ont un constructeur sans-args, et ne fonctionnera pas pour certains types de classes récursives (par exemple une classe avec une propriété de son propre type, comme un arbre). Vous pouvez également pré-remplir plus de classes dans le constructeur statique.

public static class PermutationGenerator 
{ 
    private static class Permutation<T> 
    { 
     public static IEnumerable<T> Choices { get; set; } 
    } 

    static PermutationGenerator() 
    { 
     Permutation<int>.Choices = new List<int> { -1, 0, 1 }.AsReadOnly(); 
     Permutation<string>.Choices = new List<string> { null, "", "Hello World" }.AsReadOnly(); 
    } 

    public static IEnumerable<T> GetPermutations<T>() 
    { 
     if (Permutation<T>.Choices == null) { 
      var props = typeof(T).GetProperties().Where(p => p.CanWrite); 
      Permutation<T>.Choices = new List<T>(GeneratePermutations<T>(() => Activator.CreateInstance<T>(), props)).AsReadOnly(); 
     } 
     return Permutation<T>.Choices; 
    } 

    private static IEnumerable GetPermutations(Type t) { 
     var method = typeof(PermutationGenerator).GetMethod("GetPermutations", new Type[] {}).MakeGenericMethod(t); 
     return (IEnumerable)(method.Invoke(null,new object[] {})); 
    } 

    private delegate T Generator<T>(); 

    private static IEnumerable<T> GeneratePermutations<T>(Generator<T> generator, IEnumerable<PropertyInfo> props) 
    { 
     if (!props.Any()) 
     { 
      yield return generator(); 
     } 
     else 
     { 
      var prop = props.First(); 
      var rest = props.Skip(1); 

      foreach (var propVal in GetPermutations(prop.PropertyType)) 
      { 
       Generator<T> gen =() => 
       { 
        var obj = generator(); 
        prop.SetValue(obj, propVal, null); 
        return (T)obj; 
       }; 
       foreach (var result in GeneratePermutations(gen, rest)) 
       { 
        yield return result; 
       } 
      } 
     } 
    } 
} 
+0

2 problèmes avec ceci: 1) Ce n'est pas vraiment la question qu'il a posée (elle correspond au titre de la question, mais pas au contenu). 2) La solution récursive n'est pas vraiment la meilleure idée dans ce cas. Lisez ceci: http://msdn.microsoft.com/en-us/library/aa302371.aspx –

+0

Wow! Excellent travail! Ce n'est pas parfait, mais je dois dire que je suis impressionné. Je te veux dans mon équipe! : P – Martin

+0

@Joel Coehorn - pouvez-vous élaborer sur 1? Si vous appelez PermutationGenerator.GetPermutations () comme dans la question, vous obtiendrez un ensemble d'objets Client avec toutes les combinaisons des différentes propriétés définies, comme demandé. – kvb

-1

C'est comme demander de déplacer la Grande Muraille de Chine en 1 heure, dans l'espace. Cela ne peut pas être fait.

Vous auriez besoin de savoir ce qui définit chaque permutation de chaque type, même les types que vous n'avez pas créés, et c'est impossible.

+0

vous pouvez déplacer la Grande Muraille de Chine dans l'espace en 1 heure ... si vous avez les ressources: P – Aziz

+0

Oui, et vous pouvez le faire techniquement en utilisant la récursivité et la réflexion, mais ce serait horrible à regarder et lent . Et la seule utilisation serait pour tester, et je ne vois pas comment tester toutes les permutations possibles serait utile. – Samuel

1

La plupart des objets alloués dynamiquement non triviaux - comme les chaînes - n'ont pas une quantité finie de "permutations" différentes dans lesquelles ils peuvent être. Cette chaîne peut être aussi longue que vous le voulez jusqu'à ce que votre RAM soit épuisée.

Donc, c'est vraiment une tâche complètement Sisyphe, et ça ne sert à rien de le faire, sauf si vous mettez beaucoup plus de restrictions sur les types de permutations que vous recherchez.

4

Le cadre de test PEX fait quelque chose le long des lignes. Il tente de fournir plusieurs permutations de paramètres de méthode de sorte que les cas de test potentiellement utiles soient couverts.

0

Comme beaucoup l'ont dit, la génération de toutes les permutations est infaisable par calcul pour les classes non triviales. Ce que j'ai dû faire, et qui a eu beaucoup de succès, génère toutes les permutations d'une classe pour une gamme spécifique d'intrants; c'est-à-dire, étant donné une classe avec les propriétés A, B et C, je voudrais générer toutes les permutations de A = 1, A = 2, B = 1, C = 3 et C = 4, résultant en:

A = 1, B = 1, C = 3

A = 2, B = 1, C = 3

A = 1, B = 1, C = 4

A = 2, B = 1, C = 4

Ce genre de chose peut être accompli avec des algorithmes récursifs ou des requêtes LINQ vraiment élégantes. Il y a un morceau assez exhaustif sur ce here, mais c'est une bonne quantité de programmation et cela aide vraiment si vous êtes optimiste sur votre Set Theory.

Questions connexes