我正在读取一个类似
的文件HDR…
LIN…
LIN…
LIN…
HDR…
LIN…
LIN…
现在LIN对应于订单项,并且属于其上方的HDR行。
此外,数据映射来自已反序列化的xml。它具有映射关系,例如,哪个属性将数据存储在Header或LineItems类中,选择多少个字符,是否需要等。
用于存储数据的标头模型如下
public class Header
{
public string Id { get; set; }
public string Description { get; set; }
public List<Item> LineItems { get; set; }
}
我正在尝试使用通用函数在处理数据之前先加载数据。
我需要帮助
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;
}
本文Adding items to List<T> using reflection显示了如何执行此操作,但这仅在主要对象上进行。就我而言,我需要填充data[index].LineItems.Add(...)
答案 0 :(得分:1)
这是否需要通过反射来完成?您可以创建一个简单的接口,所有类似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;
}
答案 1 :(得分: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()
时,该值将强制转换为正确的类型,然后传递给List<T>.Add()
。