如何在.Net中迭代类的子级
本文关键字:迭代 Net | 更新日期: 2023-09-27 18:21:22
我有一个C#.Net类RootObject,它包含许多不同对象类型的列表。我从ajax调用中获得一个json对象,并将其反序列化为一个RootObject实例。我想遍历根对象中的所有列表,并为它们创建数据表以传递给存储过程,但我不知道如何做到这一点。有人能帮忙吗?
public class RootObject
{
public List<Car> Car { get; set;}
public List<Plane> Plane { get; set;}
public List<Train> Train { get; set;}
}
/// <summary>
/// Returns a data table filled with the values from the input list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public DataTable CreateDataTable<T>(IEnumerable<T> list)
{
Type type = typeof(T);
var properties = type.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
foreach (T entity in list)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
/// <summary>
/// This function saves the layout specified by the the user with the ID specified
/// </summary>
/// <param name="encryptedBEMSID"></param>
/// <param name="Layout"></param>
/// <returns></returns>
public string Save(string encryptedBEMSID, string Layout)
{
// Make a list of table variable parameters to hold the results of the deserialization
List<SqlParameter> parameters = new List<SqlParameter>();
// Deserialize the json object
RootObject obj = JsonConvert.DeserializeObject<RootObject>(Layout);
PropertyInfo[] objLists = obj.GetType().GetProperties();
foreach (PropertyInfo pi in objLists)
{
string ObjectType = pi.Name; // This would be "Car", "Plane", or "Train"
string UpperObjectType = ObjectType.ToUpper();
// HERE'S WHERE I NEED HELP! I'd Like to replace Car with the class specified by ObjectType
List<Car> List = obj.Car;
DataTable dt = CreateDataTable<Car>(List);
// do stuff with the resulting data table
}
}
编辑以添加JSON
{
"Car": [
{"name": "The General", "color": "red"},
{"name": "Batmobile", "color": "blue"}
],
"Plane": [
{"name": "Air Force One", "color": "white"},
{"name": "Spirit of St. Louis", "color": "gray"},
{"name": "Wright Flyer", "color": "brown"}
],
"Train": [
{"name": "Orient Express", "color": "black"},
{"name": "Ye Olde Bullet Train", "color": "orange"}
]
}
foreach(var vehicle in vehicles) { //iterate car, plane, train
foreach(var instance in vehicle) { //iterate the general, batmobile, etc.
/* do stuff */
}
}
假设您的对象只是{name,color},您可以为此创建一个类,例如Vehicle
,然后反序列化为Dictionary<string,List<Vehicle>>
。
现在,您可以轻松地枚举字典,并从每个键中枚举车辆列表。
如果它比您展示的JSON更复杂,那么您最好直接读取JSON(使用JSON.NET)并以这种方式处理它。
您还可以在JSON中添加一个类型鉴别器(请参阅https://www.mallibone.com/post/serialize-object-inheritance-with-json.net)然后Json.NET将知道CCD_ 3字段包含CCD_。您还可以提供一个自定义序列化绑定器,用于处理由字段名定义的类型的特殊情况。您仍然需要一个基类Vehicle
,但实际的反序列化值将是预期的类型。
另外,另一种选择可能是使用Dictionary<string, Dictionary<string, object>>
来保存反序列化的JSON,因为您所做的只是将值复制到表中——您不在乎它是Car
,它只是名称和值的集合。
如果将数据表创建转移到泛型类VehicleHandler<T>
中,则可以创建一个与当前检查的属性类型匹配的类型T的实例,如下所示:-
Type vehicleListType = pi.PropertyType;
Type vehicleType = vehicleListType.GetGenericArguments()[0];
var vehicleHandlerType = typeof (VehicleHandler<>).MakeGenericType(vehicleType);
var vehicleHandler = (VehicleHandler)Activator.CreateInstance(vehicleHandlerType);
现在,您可以为该字段设置车辆并生成数据表:
vehicleHandler.SetVehicles(pi.GetValue(obj));
var dataTable = vehicleHandler.DataTable;
VehicleHandler的代码是:
public abstract class VehicleHandler
{
public abstract void SetVehicles(object listOfVehicles);
public abstract DataTable DataTable { get; }
}
public class VehicleHandler<T> : VehicleHandler
{
List<T> vehicles;
public override void SetVehicles (object listOfVehicles)
{
this.vehicles = (List<T>) listOfVehicles;
}
public override DataTable DataTable => CreateDataTable(vehicles);
public DataTable CreateDataTable(IEnumerable<T> list)
{
Type type = typeof (T);
var properties = type.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name,
Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
foreach (T entity in list)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
}