2

I have the following classes. For testing purpose, I would like to get all the possible permutations of the class Client. I know that the number can be very large, but this is not my problem for now.

Client: No (int), Name(string), Address(Address object)
Address: Street(string), Country(string), etc.

For a property of type int, I always try the same three values (-1, 0, 1), for string (null, string.Empty, "Hello World", etc.). For the base types, it works well. However, for the class Address, this is different.

In brief, I am trying to write a method generic enough to take any Type (class, etc.) and get all the possible permutations (in other words: public IEnumerable GetPermutations(Type myType)). With the help of .NET Reflection, this method would loop on all the settable properties.

Does anybody have an idea how to do that?

Thanks

4
  • where do you get the values from? do you have a list of allowed values, for example? Commented Apr 6, 2009 at 19:13
  • @Aziz: He is asking for a brute force for each possible value. Commented Apr 6, 2009 at 19:13
  • How much work do you have done already? What is the part you're having trouble with (ie. generating the permuations, storing the address info, using reflection, etc...)? Commented Apr 6, 2009 at 19:28
  • This has nothing to do with permutations. Look it up. ;) Commented Apr 6, 2009 at 20:01

6 Answers 6

4

The PEX testing framework does something along the lines. It attempts to provide several permutations of method parameters such that potentially useful test cases are covered.

Sign up to request clarification or add additional context in comments.

Comments

2

Here's a class that may get you started, though I haven't tested it much. Note that this will only work for classes that have a no-args constructor, and won't work for some types of recursive classes (e.g. a class with a property of its own type, such as a tree). You also may want to pre-populate more classes in the static constructor.

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;
                }
            }
        }
    }
}

5 Comments

2 problems with this: 1) It's not really the question he asked (it fits the question title, but not the content). 2) Recursive solution isn't really the best idea in this case. Read this: msdn.microsoft.com/en-us/library/aa302371.aspx
Wow! Amazing work! This is not perfect, but I have to say that I am impress. I want you in my team! :P
@Joel Coehorn - can you elaborate on 1? If you call PermutationGenerator.GetPermutations<Client>() as in the question, you'll get a set of Client objects with all combinations of the different properties set, as requested.
@kvb -- In GetPermutations<T>, how would you handle cases such as byte[]? There is no parameterless constructor for byte[].
You have two options: first of all, if there's a fixed set of byte[] values that you always want to use, set Permutation.Choices<byte[]> to that list in the static constructor. Otherwise, you'll need to extend the code a bit; how you do this will depend on what you want the code to do in that case.
1

Most non-trivial dynamically allocated objects -- like strings -- don't have a finite amount of different "permutations" they can be in. That string can be as long as you want until your RAM runs out.

So this is really a completely Sisyphean task, and there's no point going on with it as stated unless you put a lot more heavy restrictions on what kind of permutations you're looking for.

Comments

1

You can have a look at PEX

http://research.microsoft.com/en-us/projects/pex/default.aspx

It's a whitebox test generation tool which integrates in Visual Studio.

Comments

0

As many have said, generating all permutations is computationally infeasible for non-trivial classes. What I have had to do, and had great success with, is generating all permutations of a class for a specific range of inputs; i.e., given a class with properties A, B, and C, I'd like to generate all permutations of A=1, A=2, B=1, C=3, and C=4, resulting in:

A=1, B=1, C=3

A=2, B=1, C=3

A=1, B=1, C=4

A=2, B=1, C=4

This kind of thing can be accomplished with recursive algorithms or some really elegant LINQ queries. There's a fairly exhaustive piece on that here, but its a good amount of programming and it really helps if you're boned up on your Set Theory.

Comments

-1

That's like asking to move the Great Wall of China in 1 hour, into space. It cannot be done.

You would need to know what defines each permutation of every type, even types you didn't create, and that's impossible.

2 Comments

you can move the Great Wall of China into space in 1 hour ... if you have the resources :P
Yeah, and you can technically do it using recursion and reflection, but that would be horrible to look at and slow. And the only use would be for testing, and I don't see how testing every possible permutation would be helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.