繁体   English   中英

新增清单 <t> 使用反射的属性

[英]Adding list<t> property using reflection

我正在读取一个类似

HDR…

林…

林…

林…

HDR…

林…

林…

现在,LIN对应于订单项,并且属于其上方的HDR行。

此外,数据映射来自已经反序列化的xml。 这具有映射关系,例如,哪个属性将数据存储在Header或LineItems类中,选择多少个字符,是否需要等。

用于存储数据的标头模型如下所示

public class Header
{
    public string Id { get; set; }
    public string Description { get; set; }
    public List<Item> LineItems { get; set; }
}

我正在尝试使用通用函数在处理数据之前加载数据。

我需要帮助

  • (#1)在以下函数中:在将LineItem添加到属性之前,是否要确保属性LineItems不为null是正确的方法?
  • 如何在下面的函数中执行(#2),使用反射将lineItem添加到data[headindex-1].LineItems.Add(lineItem)

这是功能...

public static List<H> ReadFile<H, I>(ConfigTypeUploadXml uploadConfig, string fileNamePath, ref string errMsg) where H : new() where I : new()
{
    // we'll use reflections to add LineItems to data
    var properties = typeof(H).GetProperties();

    // read the file line by line and add to data. 
    var data = new List<H>();
    var headIndex = 0;
    var lineIndex = 1;

    foreach (var line in File.ReadAllLines(fileNamePath))
    {

        // read HDR line
        if (line.StartsWith("HDR"))
        {
            var header = ReadHeaderLine<H>(uploadConfig, line, errMsg);
            data.Add(header);
            headIndex += 1;
        }

        // read LIN line
        if (line.StartsWith("LIN"))
        {
            var lineItem = ReadItemLine<I>(uploadConfig, line, errMsg);

            foreach (var p in properties)
            {
                if (p.Name != "LineItems")
                    continue;

                //1) if items is null then create the object
                object items = p.GetValue(data[headIndex - 1], null);
                if (items == null)
                    p.SetValue(data[headIndex - 1], new List<I>());

                //2) add line item to data[headIndex - 1].LineItems.Add(lineItem)

            }
        }
        lineIndex += 1;
    }
    return data;
}

本文使用反射将项目添加到List <T>中,显示了如何执行此操作,但这在主要对象上。 就我而言,我需要填充data[index].LineItems.Add(...)

是否需要通过反射来完成? 您可以创建所有类似于Header的类都实现的简单接口,例如

interface IHaveLineItems
{
    void AddLineItem(object item);
}

然后可以在各种Header类上实现,例如

public class Header : IHaveLineItems
{
    public string Id { get; set; }
    public string Description { get; set; }
    public List<Item> LineItems { get; set; }

    void IHaveLineItems.AddLineItem(object item)
    {
        LineItems.Add((Item)item);
    }
}

您的循环可能会变成:

var data = new List<H>();
IHaveLineItems lastHeader = null;
var lineIndex = 1;

foreach (string line in File.ReadAllLines(fileNamePath))
{
    // read HDR line
    if (line.StartsWith("HDR"))
    {
        var header = ReadHeaderLine<H>(uploadConfig, line, errMsg);
        data.Add(header);
        lastHeader = header;
    }

    // read LIN line
    if (line.StartsWith("LIN"))
    {
        var lineItem = ReadItemLine<I>(uploadConfig, line, errMsg);
        lastHeader.AddLineItem(lineItem);
    }

    lineIndex += 1;
}

如果您想通过反射来做到这一点,则相对容易。

using System.Collections;
using System.Reflection;


var lineItem = ...;
var header = data[data.Count - 1];

var lineItemsProperty = header.GetType().GetProperty("LineItems");
var lineItems = lineItemsProperty.GetValue(header) as IList;
lineItems.Add(lineItem);

这利用了List<T>实现IList接口的事实。 当您调用IList.Add() ,该值将IList.Add()转换为正确的类型,然后传递给List<T>.Add()

暂无
暂无

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

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