【问题标题】:Iterate through any Property, nested objects and Lists C#遍历任何属性、嵌套对象和列表 C#
【发布时间】:2018-05-09 02:29:01
【问题描述】:

我得到 2 个类型为“Shipment”的对象(“Shipment1”和“Shipment2”),并且必须读取它们的每个值。如果 Shipment1 的值为 NULL/空,我想查看 Shipment2 的相同值,如果值不是 NULL/空,我必须将其复制到 Shipment1。 我试图用反射遍历我的对象,但是嵌套的对象“Consignor”、“Consignee”、“Invoices”让我失败了。我希望你能帮助我。 我有以下简化的类结构:

public class Shipment
{
    public int Id { get; set; }
    public Address Consignor { get; set; }
    public Address Consignee { get; set; }
    public IEnumerable<Invoice> Invoices{ get; set; }
} 
public class Address
{
    public string Name { get; set; }
    public string Street{ get; set; }
    public string Zip { get; set; }
    public string City{ get; set; }
    public string Country{ get; set; }
}
public class Invoice
{
    public IEnumerable<Item> Items{ get; set; }
}
public class Item
{
    public string Description{ get; set; }
    public int Amount { get; set; }
}

我试过这样。它适用于货运的顶级属性,但不适用于发货人、收货人、发票等。

            foreach (PropertyInfo info1 in shipment1.GetType().GetProperties())
        {
            var datatype = info1.PropertyType;
            switch (datatype.Name.ToLower())
            {
                case "string":

                    if (!string.IsNullOrEmpty((string)info1.GetValue(shipment1)))
                    {
                        string value= (string)info1.GetValue(shipment1);
                        string name = info1.Name;
                        Type type = input.GetType();
                        PropertyInfo info2 = shipment2.GetType().GetProperty(name);


                        if (string.IsNullOrEmpty((string)info2.GetValue(shipment2)))
                        {
                            info2.SetValue(shipment2, value, null);
                        }
                    }
                    break;

                case "integer":
                    // and so on
             }       
       }

【问题讨论】:

  • shipment1 有一个Address 的值为Zipe,但Street 没有值,而shipment2 有一个Address 时,你决定做什么? Street 的值和Zipe不同值?盲目抄袭?在这种情况下,我认为地址没有任何意义。
  • 是的,你是对的,这没有任何意义。在我的用例中,地址属性不会为空。这只是一个简化的类结构,我正在寻找一种遍历每个属性、嵌套对象等的算法。
  • 循环属性的代码在哪里?
  • 我添加了我的迭代示例

标签: c# loops reflection nested


【解决方案1】:

我最终得到了这个,让 shipment1 具有与 shipment2 相同的值,即使 shipment1 一开始为空。 p>

请注意,它会像指针一样复制 IEnumerable。复制之后,编辑copy.Invoices也会编辑source.Invoices,反之亦然。

// used for my test:
Shipment shipment1 = null;
Shipment shipment2 = new Shipment { Id = 42, Consignor = new Address { Name = "Foo1", Street = "Bar1", Zip = "Baz1", City = "Qux1", Country = "Quux1" }, Consignee = new Address { Name = "Foo2", Street = "Bar2", Zip = "Baz2", City = "Qux2", Country = "Quux2" }, Invoices = new Invoice[] { new Invoice { Items = new Item[] { new Item { Description = "FooBar1", Amount = 1 }, new Item { Description = "BazQux1", Amount = 1 } } }, new Invoice { Items = new Item[] { new Item { Description = "FooBar2", Amount = 2 }, new Item { Description = "BazQux2", Amount = 2 } } } } };
// kind of ugly but I didn't manage to do it prettier:
shipment1 = Work(shipment2, shipment1);

private T Work<T>(T source, T copy)
{
    if (source == null)
        return copy;
    if (copy == null)
        copy = Activator.CreateInstance<T>();

    foreach (PropertyInfo prop in typeof(T).GetProperties())
    {
        switch (prop.PropertyType.Name.ToLower())
        {
            case "string":
                string str = (string)prop.GetValue(source);
                if (!string.IsNullOrEmpty(str))
                    if (string.IsNullOrEmpty((string)prop.GetValue(copy)))
                        prop.SetValue(copy, str);
                break;
            case "int32":
                int i = (int)prop.GetValue(source);
                if (i != 0)
                    if ((int)prop.GetValue(copy) == 0)
                        prop.SetValue(copy, i);
                break;
            case "address":
                prop.SetValue(copy, Work(prop.GetValue(source) as Address, prop.GetValue(copy) as Address));
                break;
            case "ienumerable`1":
                switch (prop.PropertyType.GetGenericArguments()[0].Name.ToLower())
                {
                    case "invoice":
                        IEnumerable<Invoice> invoices = (IEnumerable<Invoice>)prop.GetValue(source);
                        if (invoices != null && invoices.Count() > 0)
                            if ((IEnumerable<Invoice>)prop.GetValue(copy) == null)
                                prop.SetValue(copy, invoices);
                        break;
                    // edit: this is actually useless
                    /*
                    case "item":
                        IEnumerable<Item> items = (IEnumerable<Item>)prop.GetValue(source);
                        if (items != null && items.Count() > 0)
                            if ((IEnumerable<Item>)prop.GetValue(copy) == null)
                                prop.SetValue(copy, items);
                        break;
                    */
                }
                break;
        }
    }

    return copy;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 2021-04-10
    相关资源
    最近更新 更多