我有以下对象结构:
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
}
但是正如我提到的,我还需要包含列表
,因此这些属性需要扁平化。
因此,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[...]}
]
知道我该怎么做吗?
如果您知道类型,就不需要使用反射:
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处理实现该接口的所有类型,从而提高类型的安全性。
如果您需要处理任何类型的对象,或者希望使用属性来注释属性,则可以使用反射。但这增加了相当多的复杂性,因为对象及其属性形成了一个需要遍历的图。并且需要处理循环依赖关系和许多其他潜在问题。