将PropertyDescriptor转换为List <tuple <string,string =“”>&gt;

时间:2018-03-10 09:44:50

标签: c# reflection

我有以下课程:

public class Cmp
{
    public List<Tuple<string, string>> Hdd { get; set; }
    public string Cpu { get; set; }
    public string MonitorModel { get; set; }
    public List<Tuple<string, string>> OpticDriver { get; set; }
}

我也使用此代码将List<Cmp>转换为CSV:

public static void WriteToCsv<T>(IEnumerable<T> data)
{
    var strBuilder = new StringBuilder();
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
    foreach (PropertyDescriptor prop in props)
    {
        strBuilder.Append(prop.DisplayName); // header
        strBuilder.Append(",");
    }
    strBuilder.AppendLine();
    foreach (T item in data)
    {
        foreach (PropertyDescriptor prop in props)
        {
            strBuilder.Append(prop.Converter.ConvertToString(
                prop.GetValue(item)));
            strBuilder.Append(",");
        }
        strBuilder.AppendLine();
    }

    File.WriteAllText(@"C:\list.csv", strBuilder.ToString());
}

只是想知道我如何在Hdd内对OpticDriverWriteToCsv<T>属性进行迭代。目前的结果如下:

 Hdd            Cpu     MonitorModel    OpticDriver
(Collection)    CPU1    Monitor1        (Collection)
(Collection)    CPU2    Monitor2        (Collection)
(Collection)    CPU3    Monitor3        (Collection)

我希望它是这样的:

 Hdd            Cpu     MonitorModel    OpticDriver
Hdd1-Hdd2       CPU1    Monitor1        Disk1-Disk2
Hdd1-Hdd2       CPU2    Monitor2        Disk1-Disk2
Hdd1-Hdd2       CPU3    Monitor3        Disk1-Disk2

2 个答案:

答案 0 :(得分:1)

解决方案1 ​​

将值转换为List<Tuple<string,string>>并以不同于其他属性

的方式处理它
foreach (PropertyDescriptor prop in props)
{
    var value = prop.GetValue(item);
    if(value is List<Tuple<string, string>> tupleList)
    {
        string tupleString = ConvertTupleListToString(tupleList);
        strBuilder.Append(tupleString);
    }
    else
    {
        strBuilder.Append(prop.Converter.ConvertToString(value));
    }
    strBuilder.Append(",");
}

解决方案2

不要使用通用List<Tuple<string,string>>,而应考虑使用自己的类似List的类型,并使用自定义ToString()实现,这将返回您想要的任何内容。

public class HddInfoList : List<Tuple<string, string>>
{
    public HddInfoList(IEnumerable<Tuple<string, string>> collection) : base(collection)
    {

    }

    public override string ToString()
    {
        //For example return first items of tuple separated by '-'
        return string.Join("-", this.Select(m => m.Item1));
    }
}

答案 1 :(得分:1)

对于同一HddOpticDriver,您可能分别有更多CpuMonitorModel项,因此您需要三个周期:

  • 第一个将迭代您的Cmp
  • 列表
  • 第二个将迭代给定Hdd项目的Cmp个项目
  • 第三个将使用给定的OpticDriver
  • 迭代给定Cmp项的Hdd个项目

如果你想保持WriteToCsv泛型,那么检查prop的类型,如果它是某种集合,那么你需要为它实现一个内循环。您可以迭代或递归地实现此目的,但建议使用前者。您将确保挖掘所需的所有多维元组。我建议使用一个数组来存储任意数量的迭代器,当迭代器完成它的设置时,将它设置为给定集合的第一项,然后转到数组中前一组的下一项,直到第一个迭代器完成它的工作。如果这个答案不清楚,请告诉我,我会给你算法。