Dynamisches Hinzufügen von Eigenschaften zu einem ExpandoObject

232

Ich möchte einem ExpandoObject zur Laufzeit dynamisch Eigenschaften hinzufügen. Um beispielsweise einen String-Eigenschaftsaufruf NewProp hinzuzufügen, möchte ich so etwas schreiben

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

Ist das leicht möglich?

Craig
quelle

Antworten:

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

Alternative:

var x = new ExpandoObject() as IDictionary<string, Object>;
x.Add("NewProp", string.Empty);
Stephen Cleary
quelle
31
Ich habe nie bemerkt, dass Expando IDictionary <string, object> implementiert . Ich habe immer gedacht, dass die Besetzung es in ein Wörterbuch kopieren würde. Durch Ihren Beitrag wurde mir jedoch klar, dass Sie beim Ändern des Wörterbuchs auch das zugrunde liegende ExpandoObject ändern! Vielen Dank
Dynalon
3
bekommenError 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
23
Es ist IDictionary<string, object>nicht IDictionary<string, string>.
Stephen Cleary
3
@ user123456: Eigenschaftsnamen sind immer Zeichenfolgen. Sie können nicht dynamisch sein. Wenn mit "ist eine Dynamik" gemeint ist "ist erst zur Laufzeit bekannt", müssen Sie das zweite Beispiel verwenden. Wenn von „ein dynamischer ist“, können Sie die Eigenschaft bedeuten Wert ist dynamisch, dann ist das in Ordnung. Ein dynamischer Wert funktioniert in beiden Beispielen einwandfrei.
Stephen Cleary
3
Es ist wichtig zu beachten, dass Sie beim Casting IDictionarynicht dynamicals Variablentyp verwenden.
user3791372
14

Hier ist eine Beispiel-Hilfsklasse, die ein Objekt konvertiert und ein Expando mit allen öffentlichen Eigenschaften des angegebenen Objekts zurückgibt.


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

Verwendung:

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

//Add Custom Properties
dynamicHelper.AddProperty(expandoObj, "dynamicKey", "Some Value");
Johannes
quelle
10
"var expandoDict = expando als IDictionary;" Diese Zeile muss in "var expandoDict = expando as IDictionary <String, object>;" geändert werden.
Jom George
0

Ich denke, dies fügt eine neue Eigenschaft im gewünschten Typ hinzu, ohne einen primitiven Wert festlegen zu müssen, wie wenn die Eigenschaft in der Klassendefinition definiert ist

var x = new ExpandoObject();
x.NewProp = default(string)
Morteza Ebrahim Nejad
quelle
5
Hey Morteza! Nur-Code-Antworten können das Problem lösen, aber sie sind viel nützlicher, wenn Sie erklären, wie sie es lösen. Community erfordert sowohl Theorie als auch Code, um Ihre Antwort vollständig zu verstehen.
RBT