[英]In C#, how do I change a Key-Value-Property's value while recursively traversing an ExpandoObject?
使用C#,我需要遍历从XML
ExpandoObject
转换为ExpandoObject
的对象,并用新值替换所有“ 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
没有设置器,因此我无法递归运行此方法。
任何建议表示赞赏。 谢谢!
我对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值保留在列表中,以避免第二次检索该值,但是我猜想这并不是一个重要的优化。
由于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);
}
}
我对此进行了一些测试,并通过使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;
}
它限制了类型安全性,但是根据MSDN实际上,动态似乎是与expandos交互的最佳方式,反正是您没有奢侈的地方:
“在C#中,要为ExpandoObject类的实例启用后期绑定,必须使用dynamic关键字。有关更多信息,请参见使用Type dynamic(C#编程指南)。”
这意味着,如果不使用dynamic
关键字,则将在CLR中运行Expando而不是DLR,这将产生一些奇怪的后果,例如无法设置值。 希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.