Agregar dinámicamente propiedades a un ExpandoObject


233

Me gustaría agregar dinámicamente propiedades a un ExpandoObject en tiempo de ejecución. Entonces, por ejemplo, para agregar una propiedad de cadena, llame a NewProp. Me gustaría escribir algo como

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

¿Es esto fácilmente posible?


Respuestas:


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

Alternativamente:

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

32
Nunca me he dado cuenta de que Expando implementa IDictionary <string, object>. Siempre pensé que ese elenco lo copiaría a un diccionario. Sin embargo, su publicación me hizo comprender que si cambia el Diccionario, ¡también cambia el ExpandoObject subyacente! Muchas gracias
Dynalon

3
gettingError 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

24
Es IDictionary<string, object>, no IDictionary<string, string>.
Stephen Cleary

3
@ user123456: los nombres de propiedad son siempre cadenas; No pueden ser dinámicos. Si por "es una dinámica", quiere decir "no se conoce hasta el tiempo de ejecución", entonces debe usar el segundo ejemplo. Si por "es una dinámica", quiere decir que el valor de la propiedad es dinámico, entonces está bien. Tener un valor dinámico funciona bien para cualquier ejemplo.
Stephen Cleary

3
Es importante tener en cuenta que cuando se realiza la conversión IDictionary, no se usa dynamiccomo tipo de variable.
user3791372


14

Aquí hay una clase auxiliar de muestra que convierte un Objeto y devuelve un Expando con todas las propiedades públicas del objeto dado.


    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");

11
"var expandoDict = expando como IDictionary;" esta línea debe cambiar a "var expandoDict = expando como IDictionary <String, object>;"
Jom George

0

Creo que esto agrega una nueva propiedad en el tipo deseado sin tener que establecer un valor primitivo, como cuando la propiedad se define en la definición de clase

var x = new ExpandoObject();
x.NewProp = default(string)

55
¡Hola Morteza! Las respuestas de solo código pueden resolver el problema, pero son mucho más útiles si explica cómo lo resuelven. La comunidad requiere tanto teoría como código para comprender su respuesta por completo.
RBT
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.