【发布时间】:2014-11-19 16:46:32
【问题描述】:
我有一个设计,其中类包含一个 List 对象,每个 Summary 都是半动态属性的字典。也就是说,给定列表中的每个摘要都将在字典中具有相同的键。我正在使用这种设计来构建一组动态“属性”来跟踪汇总值,因为根据我的项目规范,这些汇总值将在运行时进行配置。
问题是:我怎样才能展平这个列表,以便列表中的每个项目都被视为字典中的键是实际属性?
我尝试了将字典转换为列表的不同变体,但这似乎本质上是错误的,因为我确实需要将键视为属性。我猜我需要使用 C# 4.0+ 和 ExpandoObject 的新动态特性,但我不能完全正确。
下面的代码显示了基本设置,“flattenedSummary”给了我我想要的——一个动态类型的新列表,其属性是摘要字典的键。但是,这是有缺陷的,因为我已经对属性名称进行了硬编码,而我不能这样做,因为直到运行时我才真正知道它们。
flattenedSummary2 版本尝试将列表展平,但由于返回的类型仍然是 List 而不是我想要的 List,因此未能实现。
public class Summary : Dictionary<string, object>
{
}
public class ClassA
{
public List<Summary> Summaries = new List<Summary>();
}
static void Main(string[] args)
{
ClassA a = new ClassA();
var summary = new Summary();
summary.Add("Year", 2010);
summary.Add("Income", 1000m);
summary.Add("Expenses", 500m);
a.Summaries.Add(summary);
summary = new Summary();
summary.Add("Year", 2011);
summary.Add("Income", 2000m);
summary.Add("Expenses", 700m);
a.Summaries.Add(summary);
summary = new Summary();
summary.Add("Year", 2012);
summary.Add("Income", 1000m);
summary.Add("Expenses", 800m);
a.Summaries.Add(summary);
var flattenedSummary = from s in a.Summaries select new { Year = s["Year"], Income = s["Income"], Expenses = s["Expenses"] };
ObjectDumper.Write(flattenedSummary, 1);
var flattenedSummary2 = Convert(a);
ObjectDumper.Write(flattenedSummary2, 1);
Console.ReadKey();
}
public static List<ExpandoObject> Convert(ClassA a)
{
var list = new List<ExpandoObject>();
foreach (Summary summary in a.Summaries)
{
IDictionary<string, object> fields = new ExpandoObject();
foreach (var field in summary)
{
fields.Add(field.Key.ToString(), field.Value);
}
dynamic s = fields;
list.Add(s);
}
return list;
}
【问题讨论】:
-
那么,如果您在运行时才知道它们是什么,那么您如何在代码中使用这些属性呢?这只是用于数据绑定还是您自己从不直接使用属性?
-
使用这种扁平化视图的两种方式:数据绑定到网格以进行调试和从 web api 序列化为 json(或 xml)。有关提供 json 解决方案的细微更改,请参阅下面的 cmets 接受的答案。
标签: c# linq dictionary dynamic-properties