Ajout dynamique de propriétés à un ExpandoObject

233

Je voudrais ajouter dynamiquement des propriétés à un ExpandoObject au moment de l'exécution. Ainsi, par exemple, pour ajouter une propriété de chaîne, appelez NewProp, je voudrais écrire quelque chose comme

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

Est-ce que c'est facilement possible?

Craig
la source

Réponses:

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

Alternativement:

var x = new ExpandoObject() as IDictionary<string, Object>;
x.Add("NewProp", string.Empty);
Stephen Cleary
la source
32
Je n'ai jamais réalisé qu'Expando implémente IDictionary <chaîne, objet>. J'ai toujours pensé que le casting le copierait dans un dictionnaire. Cependant, votre message m'a fait comprendre que si vous changez le dictionnaire, vous changez également le ExpandoObject sous-jacent! Merci beaucoup
Dynalon
3
obtenirError 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
Ce n'est IDictionary<string, object>pas le cas IDictionary<string, string>.
Stephen Cleary
3
@ user123456: Les noms de propriété sont toujours des chaînes; ils ne peuvent pas être dynamiques. Si par "est une dynamique", vous voulez dire "n'est pas connu avant l'exécution", alors vous devez utiliser le deuxième exemple. Si par "est une dynamique", vous voulez dire que la valeur de la propriété est dynamique, alors ça va. Avoir une valeur dynamique fonctionne très bien pour l'un ou l'autre exemple.
Stephen Cleary
3
Il est important de noter que lorsque vous effectuez un cast, IDictionaryvous ne l'utilisez pas dynamiccomme type de variable.
user3791372
14

Voici un exemple de classe d'assistance qui convertit un objet et renvoie un Expando avec toutes les propriétés publiques de l'objet donné.


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

Usage:

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

//Add Custom Properties
dynamicHelper.AddProperty(expandoObj, "dynamicKey", "Some Value");
Johannes
la source
11
"var expandoDict = expando as IDictionary;" cette ligne doit être remplacée par "var expandoDict = expando as IDictionary <String, object>;"
Jom George
0

Je pense que cela ajoute une nouvelle propriété dans le type souhaité sans avoir à définir une valeur primitive, comme lorsque la propriété est définie dans la définition de classe

var x = new ExpandoObject();
x.NewProp = default(string)
Morteza ebrahim nejad
la source
5
Hé Morteza! Les réponses uniquement codées peuvent résoudre le problème, mais elles sont beaucoup plus utiles si vous expliquez comment elles le résolvent. La communauté a besoin de la théorie ainsi que du code pour comprendre pleinement votre réponse.
RBT