从另一个对象生成所有可能的对象组合

时间:2017-01-30 17:38:34

标签: c#

假设我有以下对象:

public class Foo
    {
        public int? Prop1 { get; set; }
        public int? Prop2 { get; set; }
        public int? Prop3 { get; set; }
    }

初始化如下:

var test = new Foo(){
    Prop1 = 10,
    Prop2 = 20,
    Prop3 = 30
}

我想生成一个包含这些属性的所有可能组合的列表。 以下列表可能是一个结果(基本上是一个包含所有可能组合的列表):

List[0] = new Foo{Prop1 = 10, Prop2 = null, Prop3 = null};
List[1] = new Foo{Prop1 = null, Prop2 = 20, Prop3 = null}
List[2] = new Foo{Prop1 = null, Prop2 = null, Prop3 = 30};
List[3] = new Foo{Prop1 = 10, Prop2 = 20, Prop3 = null};
List[4] = new Foo{Prop1 = 10, Prop2 = null, Prop3 = 30};
List[5] = new Foo{Prop1 = null, Prop2 = 20, Prop3 = 30};
List[6] = new Foo{Prop1 = 10, Prop2 = 20, Prop3 = 30};

我正在考虑使用linq或反射来尝试导航所有属性并执行....当然,它可以通过大量的手动添加来完成,手动获取所有组合并以长代码结束,但我确信有一种更简单的方法来实现它,所以......非常感谢。< / p>

由于

1 个答案:

答案 0 :(得分:2)

hideous 危险方法将生成任意对象的组合列表:

public List<T> CombinationsOf<T>(T template)
{
    var properties = typeof(T).GetProperties().Where(prop => prop.CanRead && prop.CanWrite).ToArray();
    var combinations = 1 << properties.Length;
    var result = new List<T>(combinations - 1);
    for (var i = 1; i < combinations; i++)
    {
        var instance = (T)Activator.CreateInstance(typeof(T));
        var bits = i;
        for (var p = 0; p < properties.Length; p++)
        {
            properties[p].SetValue(instance, (bits % 2 == 1) ? properties[p].GetValue(template) : properties[p].PropertyType.IsValueType ? Activator.CreateInstance(properties[p].PropertyType) : null);
            bits = bits >> 1;
        }

        result.Add(instance);
    }

    return result;
}

用法:

var result = CombinationsOf(new Foo { Prop1 = 10, Prop2 = 20, Prop3 = 30 });

如果您希望“缺失”组合都是默认值,则可以将外循环初始化程序更改为i = 0

警告:此代码很危险 - 它:

  • 设置可能破坏内部状态的私有属性。
  • 调用可能会运行导致副作用的代码的属性设置器和getter。
  • 如果&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;运算符将换行,您将生成错误数量的组合......
  • ...如果你没有遇到可能与c发生的OutOfMemoryException。 25个属性及以上由于组合数量巨大。