使用C#,我需要遍历从ExpandoObject
投射到XML
的对象,并用新值替换任何“price”属性。
此对象非常非结构化,并且具有多层嵌套节点(实际上是嵌套的ExpandoObjects)。更具体地说,层次结构可能如下所示:
产品=>价格,数量,配件
每个配件可能都有价格和数量,本身可能有配件,这就是我需要递归的原因。
public ExpandoObject UpdatePricing(ExpandoObject exp)
{
//Is there a price property?
var hasPrice = exp.Any(a => a.Key == "price");
if (hasPrice)
{
//update price here
exp.price = 0; //Some other price
}
//Now loop through the whole object. If any of the properties contain an expando, then call this method again
foreach (var kvp in exp)
{
if (kvp.Value is ExpandoObject)
{
//THIS CODE IS NO GOOD BECAUSE kvp.Value has no setter!!
kvp.Value = UpdatePricing(kvp.Value);
}
}
return exp;
}
我遇到的问题是kvp.Value
没有setter,所以我不能递归地运行这个方法。
任何建议都表示赞赏。谢谢!
答案 0 :(得分:2)
由于ExpandoObject
实现IDictionary<string, Object>
,事情可以变得更容易一些。我们还可以将返回类型更改为void
,因为我们不需要重新分配结果。
void UpdatePrice(ExpandoObject expando, decimal price)
{
var map = (IDictionary<string, Object>)expando;
if (map.ContainsKey("price"))
map["price"] = price;
foreach (var value in map.Values)
{
if (value is ExpandoObject)
UpdatePrice((ExpandoObject)value, price);
}
}
答案 1 :(得分:1)
我对ExpandoObject一无所知。但是,与大多数字典实现一样,我假设一般情况下,如果您希望将键值对更新为具有不同的值,则需要通过字典界面。
请注意,您(可能)在您枚举其内容时不允许修改字典。因此,您需要构建要更新的元素列表,并在单独的操作中执行此操作。
例如:
List<string> keysToUpdate = new List<string>();
foreach (var kvp in exp)
{
if (kvp.Value is ExpandoObject)
{
keysToUpdate.Add(kvp.Key);
}
}
foreach (string key in keysToUpdate)
{
exp[key] = UpdatePricing(exp[key]);
}
您还可以将整个KeyValuePair值保留在列表中,以避免第二次检索值,但我猜测这不是一个重要的优化。
答案 2 :(得分:1)
我刚刚对此进行了一些测试,并且能够通过让expando充满活力来实现它:
public static ExpandoObject DoWork(ExpandoObject obj)
{
dynamic expando = obj;
//update price
if (obj.Any(c => c.Key == "price"))
expando.price = 354.11D;
foreach (var item in expando)
{
if (item.Value is ExpandoObject)
{
//call recursively
DoWork(item.Value);
}
}
return expando;
}
它可以消除类型安全,但看起来你似乎没有那种奢侈,动态是与{expand}实际上根据MSDN进行交互的最佳方式:
&#34;在C#中,为ExpandoObject的实例启用后期绑定 class,你必须使用dynamic关键字。有关更多信息,请参阅 使用Type dynamic(C#编程指南)。&#34;
这意味着如果您不使用dynamic
关键字,则在CLR中运行Expando而不是DLR,这会产生一些奇怪的后果,例如无法设置值。希望这会有所帮助。