动态地将嵌套属性添加到ExpandoObject

时间:2012-11-30 22:16:50

标签: c# dynamic expandoobject

我正在获取一个JSON对象(可能包含多个级别的JSON数组等),我想将其转换为ExpandoObject。

我想出了如何在运行时向ExpandoObject添加简单属性,因为它实现了IDictionary,但是如何添加嵌套属性(例如myexpando.somelist.anotherlist.someitem之类的内容)在运行时,将正确解决?

编辑:目前这适用于简单(第一级)属性:

var exo = new ExpandoObject() as IDictionary<String, Object>;
exo.Add(name, value);

问题是如何使名称嵌套,并使ExpandoObject相应地解析。

4 个答案:

答案 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" />