Create a set of objects with multiple properties

I have an object with several logical (and integer) properties. I want to create a collection of objects with many different properties in order to have a good dataset used for tests.

for instance

public class A { public int value {get; set;} //want to try beetween 0 and 5 public bool foo {get; set;} public bool bar {get; set;} public bool boo {get; set;} } 

In this example, I like to have a list with 6 * 2 * 2 = 24 elementw, with value = 0/1/2/3/4/5, foo = true / false, bar = true / false, but boo always false.

I could do this using 24 lines of code. But this is a lot, and if I have another bool, it doubles the number of rows.

I can use one loop for each property, but I don't think this is a good way to have too many nested loops. I can also do this by thinking, but I think it is too much work, right?

I think there is another way to do it better, but I do not find it.

+5
source share
3 answers

What is the problem with this old loop?

 var boolVals = new[] { true, false }; var intVals = new[] { 0, 1, 2, 3, 4, 5 }; var myList = new List<A>(); foreach(var foo in boolVals) { foreach(var value in intVals) { foreach(var bar in boolVals) { foreach (var boo in boolVals) { myList.Add(new A { value = value, foo = foo, bar = bar, boo = boo }); } } } } 

You need to add a new attachment for each property you add and loop the corresponding set of values ​​that this property can have.

This rating filters out every possible permutation of your values ​​across multiple lines of easily readable code.

Of course it looks a little ugly. But it grows with only one additional socket for each added property.

+3
source

Since you are not explicitly requesting a solution with a complete permutation, I suggest switching to random. You can use the constructor ...

 public class A { public int value {get; set;} //want to try beetween 0 and 5 public bool foo {get; set;} public bool bar {get; set;} public bool boo {get; set;} public A() { // initialize value, foo, bar, boo with desired default / random here } } var myList = new List<A>(); for (int i=0; i<=24; i++) myLyst.add(new A()); 

it seems quite readable and supported for me. You can also pass an argument to the new A () and use it to compute the nth permutation, if necessary, but I think this is beyond the scope of the question.

+1
source

You can do this using reflection and a data structure that tracks the value (through equivalent indexes) for each property

This automatically considers all the properties in the class, and you can extend it to other types of properties by simply adding ValuesFor to the dictionary

 using System; using System.Collections.Generic; using System.Reflection; public class Program { private static Dictionary<string, object[]> ValuesFor = new Dictionary<string, object[]>() { { typeof(int).ToString(), new object[] { 0, 1, 2, 3, 4, 5 } }, { typeof(bool).ToString(), new object[] { true, false } } }; public static void Main() { var properties = typeof(A).GetProperties(BindingFlags.Instance | BindingFlags.Public); int[] valueIndices = new int[properties.Length]; do { createObject(properties, valueIndices); } while (setNext(properties, valueIndices)); Console.ReadKey(); } /// <summary> /// This updates the valueIndex array to the next value /// </summary> /// <returns>returns true if the valueIndex array has been updated</returns> public static bool setNext(PropertyInfo[] properties, int[] valueIndices) { for (var i = 0; i < properties.Length; i++) { if (valueIndices[i] < ValuesFor[properties[i].PropertyType.ToString()].Length - 1) { valueIndices[i]++; for (var j = 0; j < i; j++) valueIndices[j] = 0; return true; } } return false; } /// <summary> /// Creates the object /// </summary> public static void createObject(PropertyInfo[] properties, int[] valueIndices) { var a = new A(); for (var i = 0; i < properties.Length; i++) { properties[i].SetValue(a, ValuesFor[properties[i].PropertyType.ToString()][valueIndices[i]]); } print(a, properties); } public static void print(object a, PropertyInfo[] properties) { Console.Write("Created : "); for (var i = 0; i < properties.Length; i++) Console.Write(properties[i].Name + "=" + properties[i].GetValue(a) + " "); Console.Write("\n"); } public class A { public int value { get; set; } public bool foo { get; set; } public bool bar { get; set; } public bool boo { get; set; } } } 

Currently, createObject simply creates an object and calls print to print the object. Instead, you can add it to the collection and run your tests with it (or directly put your tests instead of print )


Fiddle - https://dotnetfiddle.net/oeLqc5

0
source

Source: https://habr.com/ru/post/1244566/


All Articles