我正在获取一个JSON对象(可能包含多个级别的JSON数组等),我想将其转换为ExpandoObject。
我想出了如何在运行时向ExpandoObject添加简单属性,因为它实现了IDictionary,但是如何添加嵌套属性(例如myexpando.somelist.anotherlist.someitem
之类的内容)在运行时,将正确解决?
编辑:目前这适用于简单(第一级)属性:
var exo = new ExpandoObject() as IDictionary<String, Object>;
exo.Add(name, value);
问题是如何使名称嵌套,并使ExpandoObject相应地解析。
答案 0 :(得分:5)
dynamic myexpando = new ExpandoObject();
myexpando.somelist = new ExpandoObject() as dynamic;
myexpando.somelist.anotherlist = new ExpandoObject() as dynamic;
myexpando.somelist.anotherlist.someitem = "Hey Hey There! I'm a nested value :D";
答案 1 :(得分:1)
这样做怎么样:
var exo = new ExpandoObject() as IDictionary<String, Object>;
var nested1 = new ExpandoObject() as IDictionary<String, Object>;
exo.Add("Nested1", nested1);
nested1.Add("Nested2", "value");
dynamic d = exo;
Console.WriteLine(d.Nested1.Nested2); // Outputs "value"
答案 2 :(得分:1)
您可以通过在调用TryGetValue
时存储对先前检索的对象或词典的引用来执行此操作。我使用了如下所示的类:
public DynamicFile(IDictionary<string, object> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
_dictionary = dictionary;
_lastGetRef = _dictionary;
}
private readonly IDictionary<string, object> _dictionary;
private IDictionary<string, object> _lastGetRef;
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (!_dictionary.TryGetValue(binder.Name, out result))
{
result = null;
return true;
}
var dictionary = result as IDictionary<string, object>;
if (dictionary != null)
{
result = new DynamicFile(dictionary);
_lastGetRef = dictionary;
return true;
}
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if(_dictionary.ContainsKey(binder.Name))
_dictionary[binder.Name] = value;
else if (_lastGetRef.ContainsKey(binder.Name))
_lastGetRef[binder.Name] = value;
else
_lastGetRef.Add(binder.Name, value);
return true;
}
_dictionary
由构造函数在创建动态对象时设置,然后设置为最后的最后一个引用字典。这是因为Dictionarys是类,因此是引用类型。
要正确嵌套,您需要在每个嵌套级别实例化每个字典,就像多维数组一样。例如:
myexpando.somelist = new Dictionary<string, object>();
myexpando.somelist.anotherlist = new Dictionary<string, object>();
myexpando.somelist.anotherlist.someitem = "Hey Hey There! I'm a nested value :D";
您可能会在TryGetMember
中编写一些代码,当密钥不存在时会自动添加一个字典,但我不需要这样,所以我没有添加它。
答案 3 :(得分:0)
非常简单
<强>扩展强>
public static class ObjectExtension
{
public static ExpandoObject ToExpando(this object source)
{
IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(source);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
}
客户行动
public IActionResult Client(string username)
{
var client = HttpContext.Items["profile"] as Client;
var model = new
{
client.Id,
client.Name,
client.Surname,
client.Username,
client.Photo,
CoverPhoto = new {
client.CoverPhoto.Source,
client.CoverPhoto.X
}.ToExpando(),
}.ToExpando();
return View(model);
}
<强> Client.cshtml 强>
<img id="cover-photo" src="@Model.CoverPhoto.Source" />