Adicionando propriedades dinamicamente a um ExpandoObject

233

Gostaria de adicionar dinamicamente propriedades a um ExpandoObject em tempo de execução. Por exemplo, para adicionar uma propriedade de string, chame NewProp, gostaria de escrever algo como

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

Isso é facilmente possível?

Craig
fonte

Respostas:

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

Alternativamente:

var x = new ExpandoObject() as IDictionary<string, Object>;
x.Add("NewProp", string.Empty);
Stephen Cleary
fonte
32
Eu nunca percebi que o Expando implementa o IDictionary <string, object>. Eu sempre pensei que o elenco iria copiá-lo para um dicionário. No entanto, sua postagem me fez entender que, se você alterar o Dicionário, também altera o ExpandoObject! Muito obrigado
Dynalon
3
ObtendoError 53 Cannot convert type 'System.Dynamic.ExpandoObject' to 'System.Collections.Generic.IDictionary<string,string>' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion
TheVillageIdiot 30/10/12
24
É IDictionary<string, object>, não IDictionary<string, string>.
precisa
3
@ user123456: Os nomes das propriedades são sempre strings; eles não podem ser dinâmicos. Se por "é uma dinâmica", você quer dizer "não é conhecido até o tempo de execução", é necessário usar o segundo exemplo. Se por "é uma dinâmica", você quer dizer que o valor da propriedade é dinâmico, tudo bem. Ter um valor dinâmico funciona bem para qualquer exemplo.
Stephen Cleary
3
É importante observar que, quando você está transmitindo, IDictionarynão usa dynamiccomo tipo de variável.
User3791372
14

Aqui está uma classe auxiliar de amostra que converte um Objeto e retorna um Expando com todas as propriedades públicas do objeto especificado.


    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;
                if (expandoDict.ContainsKey(propertyName))
                    expandoDict[propertyName] = propertyValue;
                else
                    expandoDict.Add(propertyName, propertyValue);
            }
        }

Uso:

//Create Dynamic Object
dynamic expandoObj= dynamicHelper.convertToExpando(myObject);

//Add Custom Properties
dynamicHelper.AddProperty(expandoObj, "dynamicKey", "Some Value");
Johannes
fonte
11
"var expandoDict = expando como IDictionary;" essa linha precisa mudar para "var expandoDict = expando como IDictionary <String, objeto>;"
precisa
0

Eu acho que isso adicionar nova propriedade no tipo desejado sem ter que definir um valor primitivo, como quando a propriedade definida na definição de classe

var x = new ExpandoObject();
x.NewProp = default(string)
Morteza ebrahim nejad
fonte
5
Ei Morteza! Respostas somente de código podem resolver o problema, mas são muito mais úteis se você explicar como elas o resolvem. A comunidade requer teoria e código para entender sua resposta completamente.
RBT