I want to save data-class instance to database and load it from database. and I want to generate sql command automatically. so, I think that I need to use dictionary< string, string> so that solve it.
refer my old question : How to convert 2D string array to 2D [int, double, bool, ..] array?
working process like these.
- convert data-class instance to dictionary < string, string>.
- save/load dictionary to/from txt, database, etc.
- convert dictionary to data-class instance
I think I have solved the problem anyway. but I think converting 2D array method is still not a perfect one. I wonder, when I call FieldInfo.SetValue function, is there another way to solve type conversion without using switch/case state like my solution.
help me simplify my code.
Data class like this
public class DCylinderData
{
public int ID;
public int[] Solenoid = new int[2];
public int[] UpSensor = new int[DEF_MAX_CYLINDER_SENSOR];
public int[] DownSensor = new int[DEF_MAX_CYLINDER_SENSOR];
public double MovingTime;
public ECylinderType CylinderType;
public ESolenoidType SolenoidType;
public bool[] boolTest = new bool[3];
public string[] nameTest = new string[2];
public int[,] TwoDimension = new int[3,4];
public DCylinderData()
{
}
}
main code like this
// 0. initialize
DCylinderData cylData = new DCylinderData();
cylData.ID = 99;
cylData.MovingTime = 1.1;
cylData.CylinderType = ECylinderType.UPSTREAM_DOWNSTREAM;
cylData.Solenoid = new int[]{ 2, 3};
for (int i = 0; i < 2 ; i++)
{
cylData.Solenoid[i] = i + 2;
cylData.nameTest[i] = $"NameTest_{i}";
}
for (int i = 0; i < DEF_MAX_CYLINDER_SENSOR; i++)
{
cylData.UpSensor[i] = i * 1;
cylData.DownSensor[i] = i * 4;
}
for (int i = 0; i < cylData.TwoDimension.GetLength(0) ; i++)
{
for (int j = 0; j < cylData.TwoDimension.GetLength(1) ; j++)
{
cylData.TwoDimension[i, j] = i * cylData.TwoDimension.GetLength(1) + j;
}
}
cylData.boolTest[0] = true;
cylData.boolTest[1] = false;
cylData.boolTest[2] = true;
// 1. Class -> Dictionary
Dictionary<string, string> fieldBook = new Dictionary<string, string>();
Type type = typeof(DCylinderData);
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields)
{
// 1.1 element
if (field.FieldType.IsValueType)
{
fieldBook.Add(field.Name, field.GetValue(cylData).ToString());
}
// 1.2 array
else if (field.FieldType.IsArray)
{
Array array = (Array)field.GetValue(cylData);
// 1.2.1 1-D array
if (array.Rank == 1)
{
for (int i = 0; i < array.GetLength(0); i++)
{
fieldBook.Add($"{field.Name}__{i}", array.GetValue(i).ToString());
}
}
// 1.2.2 2-D array
else if (array.Rank == 2)
{
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
fieldBook.Add($"{field.Name}__{i}__{j}", array.GetValue(i, j).ToString());
}
}
}
else
{
WriteLine($"Not support {field.Name}'s array {array.Rank} dimension.");
}
}
else
{
WriteLine($"Not support to handle {field.Name}'s {field.FieldType.ToString()}");
}
}
// 2. print Dictionary
foreach (KeyValuePair<string, string> item in fieldBook)
{
WriteLine($"FieldBook {item.Key} : {item.Value}");
}
// 3. Dictionary -> Class
DCylinderData copyData = new DCylinderData();
foreach (FieldInfo field in fields)
{
// 3.1 handle element
if (field.FieldType.IsValueType && fieldBook.ContainsKey(field.Name))
{
SetFieldValue(copyData, field, fieldBook[field.Name]);
}
// 3.2 handle array
else if (field.FieldType.IsArray)
{
Array array = (Array)field.GetValue(copyData);
string key, value;
// 3.2.1 1-D array
if (array.Rank == 1)
{
var arr_1d = new string[array.GetLength(0)];
for (int i = 0; i < array.GetLength(0); i++)
{
key = $"{field.Name}__{i}";
value = fieldBook.ContainsKey(key) ? fieldBook[key] : "";
arr_1d.SetValue(value, i);
}
SetFieldValue(copyData, field, arr_1d);
}
// 3.2.1 2-D array
else if (array.Rank == 2)
{
var arr_2d = new string[array.GetLength(0), array.GetLength(1)];
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
key = $"{field.Name}__{i}__{j}";
value = fieldBook.ContainsKey(key) ? fieldBook[key] : "";
arr_2d.SetValue(value, i, j);
}
}
SetFieldValue(copyData, field, arr_2d);
}
else
{
WriteLine($"Not support {field.Name}'s array {array.Rank} dimension.");
}
}
// 3.3 not support
else
{
WriteLine($"Not support to handle {field.Name}'s {field.FieldType.ToString()}");
}
}
WriteLine("Press any key to continue");
ReadLine();
and, SetFieldValue Functions like these
public static void SetFieldValue(Object target, FieldInfo fieldInfo, string value)
{
string fieldType = fieldInfo.FieldType.Name;
fieldType = fieldType.ToLower();
switch (fieldType)
{
case "boolean":
bool b;
fieldInfo.SetValue(target, bool.TryParse(value, out b) ? b : false);
break;
case "int32":
int n;
fieldInfo.SetValue(target, int.TryParse(value, out n) ? n : 0);
break;
case "double":
double d;
fieldInfo.SetValue(target, double.TryParse(value, out d) ? d : 0);
break;
case "string":
fieldInfo.SetValue(target, value);
break;
}
}
public static void SetFieldValue(Object target, FieldInfo fieldInfo, string[] arr)
{
string fieldType = fieldInfo.FieldType.Name;
fieldType = fieldType.ToLower();
fieldType = fieldType.Replace("[]", "");
switch (fieldType)
{
case "boolean":
bool b;
bool[] arr_b = Array.ConvertAll(arr, s => bool.TryParse(s, out b) ? b : false);
fieldInfo.SetValue(target, arr_b);
break;
case "int32":
int n;
int[] arr_n = Array.ConvertAll(arr, s => int.TryParse(s, out n) ? n : 0);
//int[] arr_n1 = Array.ConvertAll(arr, int.Parse);
//int[] arr_n2 = arr.Select(s => int.TryParse(s, out n) ? n : 0).ToArray();
fieldInfo.SetValue(target, arr_n);
break;
case "double":
double d;
double[] arr_d = Array.ConvertAll(arr, s => double.TryParse(s, out d) ? d : 0);
fieldInfo.SetValue(target, arr_d);
break;
case "string":
fieldInfo.SetValue(target, arr);
break;
}
}
public static void SetFieldValue(Object target, FieldInfo fieldInfo, string[,] arr)
{
string fieldType = fieldInfo.FieldType.Name;
fieldType = fieldType.ToLower();
fieldType = fieldType.Replace("[,]", "");
// 0. string return
switch (fieldType)
{
case "string":
fieldInfo.SetValue(target, arr);
return;
break;
}
// 1. initialize
int n;
double d;
bool b;
//object[,] output = new object[arr.GetLength(0), arr.GetLength(1)];
int[,] output_n = new int[arr.GetLength(0), arr.GetLength(1)];
bool[,] output_b = new bool[arr.GetLength(0), arr.GetLength(1)];
double[,] output_d = new double[arr.GetLength(0), arr.GetLength(1)];
// 2. convert
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
switch (fieldType)
{
case "boolean":
output_b[i, j] = bool.TryParse(arr[i, j], out b) ? b : false;
break;
case "int32":
output_n[i, j] = int.TryParse(arr[i, j], out n) ? n : 0;
break;
case "double":
output_d[i, j] = double.TryParse(arr[i, j], out d) ? d : 0;
break;
}
}
}
// 2. setvalue
//fieldInfo.SetValue(target, output);
switch (fieldType)
{
case "boolean":
fieldInfo.SetValue(target, output_b);
break;
case "int32":
fieldInfo.SetValue(target, output_n);
break;
case "double":
fieldInfo.SetValue(target, output_d);
break;
}
}
this is all part of my code.