简体   繁体   English

生成类的所有可能排列

[英]Generate all the possible permutations of a class

I have the following classes. 我有以下课程。 For testing purpose, I would like to get all the possible permutations of the class Client. 为了进行测试,我希望获得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) 客户端:否(int),名称(字符串),地址(地址对象)
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.). 对于int类型的属性,我总是尝试对字符串(null,string.Empty,“ Hello World”等)使用相同的三个值(-1、0、1)。 For the base types, it works well. 对于基本类型,它运行良好。 However, for the class Address, this is different. 但是,对于Address类,这是不同的。

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)). 简而言之,我正在尝试编写一种通用的方法,以采用任何类型(类等)并获取所有可能的排列(换句话说:公共IEnumerable GetPermutations(Type myType))。 With the help of .NET Reflection, this method would loop on all the settable properties. 借助.NET Reflection,此方法将在所有可设置的属性上循环。

Does anybody have an idea how to do that? 有人知道该怎么做吗?

Thanks 谢谢

The PEX testing framework does something along the lines. PEX测试框架会做一些事情。 It attempts to provide several permutations of method parameters such that potentially useful test cases are covered. 它试图提供方法参数的多个排列,以便涵盖可能有用的测试用例。

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

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. 大多数非平凡的动态分配对象(例如字符串)都没有一定数量的不同“排列”。在RAM耗尽之前,该字符串可以任意设置。

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. 因此,这实际上是完全西西弗斯式的任务,除非您对要寻找的排列方式施加了很多严格的限制,否则就没有说明的意义。

You can have a look at PEX 您可以看一下PEX

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

It's a whitebox test generation tool which integrates in Visual Studio. 这是一个集成在Visual Studio中的白盒测试生成工具。

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; 我必须做的并取得了巨大的成功,就是针对特定的输入范围生成类的所有排列。 ie, 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,B和C的类,我想生成A = 1,A = 2,B = 1,C = 3和C = 4的所有排列,结果是:

A=1, B=1, C=3 A = 1,B = 1,C = 3

A=2, B=1, C=3 A = 2,B = 1,C = 3

A=1, B=1, C=4 A = 1,B = 1,C = 4

A=2, 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. 这种事情可以通过递归算法或一些非常优雅的LINQ查询来完成。 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. 有一个关于一个相当详尽的一块在这里 ,但它的编程量好,它确实帮助,如果你在你的集理论去骨起来。

That's like asking to move the Great Wall of China in 1 hour, into space. 这就像要求将中国长城在1小时内移入太空。 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. 您将需要知道是什么定义了每种类型的每个排列,甚至不是您创建的类型,这是不可能的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM