简体   繁体   English

您如何遍历.Net中某个班级的孩子?

[英]How do you iterate over children of a class in .Net?

I have a C# .Net class RootObject which contains a number of lists of various object types. 我有一个C#.Net类RootObject,其中包含许多各种对象类型的列表。 I get a json object from an ajax call and deserialize it into a RootObject instance. 我从ajax调用中获得一个json对象,并将其反序列化为RootObject实例。 I would like to iterate over all the lists in my root object and create data tables for them to pass to a stored procedure, but I can't figure out how to do that. 我想遍历我的根对象中的所有列表,并创建数据表以将它们传递给存储过程,但是我不知道该怎么做。 Can anyone help? 有人可以帮忙吗?

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

        }
    }

EDIT TO ADD JSON 编辑以添加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 */
    }
}

Assuming your objects are just {name, color} you could create a class for that, say, Vehicle and then deserialize into a Dictionary<string,List<Vehicle>> . 假设您的对象只是{name,color},则可以为此创建一个类,例如Vehicle ,然后反序列化为Dictionary<string,List<Vehicle>>

Now you can enumerate the dictionary easily and enumerate lists of Vehicles off each key. 现在,您可以轻松枚举字典并枚举每个按键上的Vehicles列表。

If it's more complicated than the JSON you showed then you might be better off reading the JSON directly (using Json.NET) and handling it that way. 如果它比您显示的JSON更复杂,那么最好直接阅读JSON(使用Json.NET)并以这种方式进行处理。

You could also add a type discriminator to your JSON (see https://www.mallibone.com/post/serialize-object-inheritance-with-json.net ) and then Json.NET will know that the Car field contains Car objects (a fact implied but not stated in your current JSON schema). 您还可以在JSON中添加类型区分符(请参阅https://www.mallibone.com/post/serialize-object-inheritance-with-json.net ),然后Json.NET将知道Car字段包含Car对象(在您当前的JSON模式中隐含但未声明的事实)。 You may also be able to provide a custom serialization binder that handles your special situation with types defined by field names. 您也许还可以提供定制的序列化绑定程序,该绑定程序可以通过字段名称定义的类型来处理您的特殊情况。 You'd still need a base class Vehicle but the actual deserialized value would be of the type expected. 您仍然需要一个基类Vehicle但是实际的反序列化值将是预期的类型。

And, yet another option might be to use a Dictionary<string, Dictionary<string, object>> to hold the deserialized JSON since all you are doing is copying the values to a table anyway - you don't care that it's a Car , it's just a collection of names and values. 而且,另一种选择可能是使用Dictionary<string, Dictionary<string, object>>来保存反序列化的JSON,因为您要做的只是将值复制到表中-您不必关心它是Car ,它只是名称和值的集合。

If you move your datatable creation into a generic class VehicleHandler<T> you can create an instance of it with a matching type T to the type of the property you are currently examining like so:- 如果将数据表创建移动到通用类VehicleHandler<T> ,则可以创建其实例,类型T与当前正在检查的属性的类型匹配,如下所示:

Type vehicleListType = pi.PropertyType;
Type vehicleType = vehicleListType.GetGenericArguments()[0];
var vehicleHandlerType = typeof (VehicleHandler<>).MakeGenericType(vehicleType);
var vehicleHandler = (VehicleHandler)Activator.CreateInstance(vehicleHandlerType);

And now, you can set the vehicles for this field and generate the data table: 现在,您可以为此字段设置车辆并生成数据表:

vehicleHandler.SetVehicles(pi.GetValue(obj));
var dataTable = vehicleHandler.DataTable;

And the code for VehicleHandler is: 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;
    }

}

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

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