提问者:小点点

如何在C#中使用GetProperties()扁平化嵌套集合


我有以下对象结构:

public class ReportDTO
{
    public string Name { get; set; }
    public string Identifier { get; set; }
    public List<DetailsDTO> Details { get; set; }
}

public class DetailsDTO
{
    public string DetailName { get; set; }
    public string DetailAmount { get; set; }
}

并且我需要从中创建excel,如果有多个details,那么列将是重复的。因此列中的结果可能如下所示:名称标识符DetailName DetailAmount DetailName DetailAmount...

为了实现这一点,我需要使用Refleaction来获取属性。当涉及到主对象时,ReportDTO非常容易。

private void FillSheet<T>(ICollection<T> data)
{
    PropertyInfo[] properties = data.First().GetType().GetProperties();
   ... // here I'm populating sheet based on those properties
}

但是正如我提到的,我还需要包含列表中的属性;details,因此这些属性需要扁平化。

因此,var properties应该返回具有以下值的PropertyInfo[]:

[
  {System.String Name}
  {System.String Identifier}
  {System.String DetailName}
  {System.String DetailAmount}
  {System.String DetailName}
  {System.String DetailAmount}
 ...
]

取而代之的是:

[
  {System.String Name}
  {System.String Identifier}
  {System.Collections.Generic.List`1[...]}  
]

知道我该怎么做吗?


共1个答案

匿名用户

如果您知道类型,就不需要使用反射:

public static IEnumerable<string> GetValues(ReportDTO dto)
    {
        yield return dto.Name;
        yield return dto.Identifier;
        foreach (var details in dto.Details)
        {
            yield return details.DetailName;
            yield return details.DetailAmount;
        }
    }

如果这是几种可能的类型之一,您可以简单地添加检查If(data is ReportDTO report)...,或者使用模式匹配开关或访问者模式。visitor模式的优势在于,它允许您将泛型类型限制在特定接口上,编译器可以强制visitor处理实现该接口的所有类型,从而提高类型的安全性。

如果您需要处理任何类型的对象,或者希望使用属性来注释属性,则可以使用反射。但这增加了相当多的复杂性,因为对象及其属性形成了一个需要遍历的图。并且需要处理循环依赖关系和许多其他潜在问题。