动态向ExpandoObject添加属性

294

我想在运行时动态地向ExpandoObject添加属性。 例如,要添加一个名为NewProp的字符串属性,我想要编写类似于以下内容的代码:

var x = new ExpandoObject();
x.AddProperty("NewProp", System.String);

这可容易实现吗?


5个回答

611
dynamic x = new ExpandoObject();
x.NewProp = string.Empty;

或者:

var x = new ExpandoObject() as IDictionary<string, Object>;
x.Add("NewProp", string.Empty);

42
我以前从未意识到ExpandoObject实现了IDictionary<string, object>。我一直以为强制转换会将它复制到字典中。然而,你的帖子让我明白了,如果你改变字典,你也会改变底层的ExpandoObject!非常感谢。 - Dynalon
3
出现“错误53:无法通过引用转换、装箱转换、拆箱转换、包装转换或空类型转换将类型'System.Dynamic.ExpandoObject'转换为 'System.Collections.Generic.IDictionary<string,string>'”。 - TheVillageIdiot
28
它是 IDictionary<string, object>,而不是 IDictionary<string, string> - Stephen Cleary
13
需要注意的是,当你将类型转换为 IDictionary 时,不要使用 dynamic 作为变量类型。 - user3791372
2
如果您将其实现为IDictionary,则无需将其强制转换即可使用来自父类或派生类的方法: IDictionary<string, object> myExpando = new ExpandoObject(); - Abel Wenning
显示剩余7条评论

33

2
你的代码是完全错误的,你跳过了最重要的部分,也就是将其转换为字典。 - tocqueville
@tocqueville,这个答案是对当前问题的增强,而不是直接回答问题。这个答案是一个额外的可能性。希望你能理解。 - Himanshu Patel

22

这是一个示例帮助类,它将对象转换并返回一个Expando,其中包含给定对象的所有公共属性。

public static class dynamicHelper
    {
        public static ExpandoObject convertToExpando(object obj)
        {
            //Get Properties Using Reflections
            BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
            PropertyInfo[] properties = obj.GetType().GetProperties(flags);

            //Add Them to a new Expando
            ExpandoObject expando = new ExpandoObject();
            foreach (PropertyInfo property in properties)
            {
                AddProperty(expando, property.Name, property.GetValue(obj));
            }

            return expando;
        }

        public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
        {
            //Take use of the IDictionary implementation
            var expandoDict = expando as IDictionary<String, object>;
            if (expandoDict.ContainsKey(propertyName))
                expandoDict[propertyName] = propertyValue;
            else
                expandoDict.Add(propertyName, propertyValue);
        }
    }

使用方法:

//Create Dynamic Object
dynamic expandoObj= dynamicHelper.convertToExpando(myObject);
    
//Add Custom Properties
dynamicHelper.AddProperty(expandoObj, "dynamicKey", "Some Value");

16
这行代码需要修改为:"var expandoDict = expando as IDictionary<String, object>;",意思是将expando转换为一个键为字符串类型,值为对象类型的字典。 - Jom George
3
为了使其更加出色,可以将它们用作扩展方法。 - Rogerio Schmitt

2

这是我找到的最佳解决方案。但要小心使用,因为它可能无法适用于所有情况。请使用异常处理。

public static dynamic ToDynamic(this object obj)
{
    return JsonConvert.DeserializeObject<dynamic>(JsonConvert.SerializeObject(obj));
}

//你可能想使用的另一个不错的扩展方法

    public static T JsonClone<T>(this T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", nameof(source));
        }

        var serialized = JsonConvert.SerializeObject(source);
        return JsonConvert.DeserializeObject<T>(serialized);
    }

可能不如IDictionary优雅,但如果您稍后将此变量用作动态变量(例如dynamic.Properties()),则只有这种工作解决方案。 - Laky

0

这是我找到的最佳解决方案。但要小心使用。请使用异常处理,因为它可能无法适用于所有情况。

    public static dynamic ToDynamic(this object obj)
    {
        return JsonConvert.DeserializeObject<dynamic>(JsonConvert.SerializeObject(obj));
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接