Eigenschaftswert vom dynamischen C # -Objekt anhand einer Zeichenfolge abrufen (Reflektion?)


76

Stellen Sie sich vor, ich habe eine dynamische Variable:

dynamic d = *something*

Jetzt erstelle ich Eigenschaften, für ddie ich andererseits habe, aus einem String-Array:

string[] strarray = { 'property1','property2',..... }

Ich kenne die Eigenschaftsnamen nicht im Voraus.

Wie dkann ich im Code die Werte abrufen , sobald er erstellt und strarray aus der Datenbank abgerufen wurde?

Ich will bekommen d.property1 , d.property2.

Ich sehe, dass das Objekt ein _dictionaryinternes Wörterbuch hat, das die Schlüssel und die Werte enthält. Wie kann ich sie abrufen?


1
Ist somethingein IDynamicMetaObjectProvider?
SLaks

Überprüfen Sie den Laufzeittyp von somethingim Debugger und sehen Sie sich seine öffentlichen Mitglieder an.
SLaks

1
Können Sie überprüfen, was d.GetType()Sie zur Laufzeit erhalten?
Tomislav Markovski

Diese SO-Antwort zeigt, wie eine dynamische Eigenschaft abgerufen wird.
Raymond Chen

Mögliches Duplikat der Loop DynamicObject-Eigenschaften
Nawfal

Antworten:


107

Ich weiß nicht, ob es einen dynamischeren Weg mit dynamisch erstellten Objekten gibt, aber die Verwendung einer einfachen alten Reflexion sollte funktionieren:

var nameOfProperty = "property1";
var propertyInfo = myObject.GetType().GetProperty(nameOfProperty);
var value = propertyInfo.GetValue(myObject, null);

GetPropertywird zurückgegeben, nullwenn der Typ von myObjectkeine öffentliche Eigenschaft mit diesem Namen enthält.


BEARBEITEN : Wenn das Objekt kein "normales" Objekt ist, sondern etwas Implementiertes IDynamicMetaObjectProvider, funktioniert dieser Ansatz nicht. Bitte schauen Sie sich stattdessen diese Frage an:


32

Dadurch erhalten Sie alle Eigenschaftsnamen und Werte, die in Ihrer dynamischen Variablen definiert sind.

dynamic d = { // your code };
object o = d;
string[] propertyNames = o.GetType().GetProperties().Select(p => p.Name).ToArray();
foreach (var prop in propertyNames)
{
    object propValue = o.GetType().GetProperty(prop).GetValue(o, null);
}

1
Das hat wunderbar für mich funktioniert, was ich für dynamischen Typ nicht erreichen konnte, danke
Mrinal Kamboj

2
Das funktioniert nur, wenn d ein statischer Typ ist. Wenn D ein IDynamicMetaObjectProvider ist (z. B. ein JObject), erhalten Sie die falschen Eigenschaften. Wenn beispielsweise d = obj ist, wird nicht 'x' zurückgegeben, sondern die Roheigenschaften von JObject. JObject obj = JObject.FromObject (neu {x = 123});
Mike S

24

Hoffe das würde dir helfen:

public static object GetProperty(object o, string member)
{
    if(o == null) throw new ArgumentNullException("o");
    if(member == null) throw new ArgumentNullException("member");
    Type scope = o.GetType();
    IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
    if(provider != null)
    {
        ParameterExpression param = Expression.Parameter(typeof(object));
        DynamicMetaObject mobj = provider.GetMetaObject(param);
        GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[]{CSharpArgumentInfo.Create(0, null)});
        DynamicMetaObject ret = mobj.BindGetMember(binder);
        BlockExpression final = Expression.Block(
            Expression.Label(CallSiteBinder.UpdateLabel),
            ret.Expression
        );
        LambdaExpression lambda = Expression.Lambda(final, param);
        Delegate del = lambda.Compile();
        return del.DynamicInvoke(o);
    }else{
        return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
    }
}

@Ewerton Es ist schon eine Weile her, aber ich sehe, dass es System.Linq.Expressions verwendet , um den dynamischen Getter an eine Aufrufsite zu binden, und die Kompilierung der LambdaExpression überlässt . Ich weiß nicht, ob ich das aus einem dekompilierten Code oder woanders genommen habe.
IllidanS4 unterstützt Monica

6

Verwenden Sie den folgenden Code, um den Namen und den Wert der Eigenschaft eines dynamischen Objekts abzurufen.

dynamic d = new { Property1= "Value1", Property2= "Value2"};

var properties = d.GetType().GetProperties();
foreach (var property in properties)
{
    var PropertyName=property.Name; 
//You get "Property1" as a result

  var PropetyValue=d.GetType().GetProperty(property.Name).GetValue(d, null); 
//You get "Value1" as a result

// you can use the PropertyName and Value here
 }

1
Nur wenn der zugrunde liegende Typ ein einfaches Objekt ist. Es wird nicht funktionieren für Wrapper-Objekte wiePSObject
felixfbecker

5
string json = w.JSON;

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });

DynamicJsonConverter.DynamicJsonObject obj = 
      (DynamicJsonConverter.DynamicJsonObject)serializer.Deserialize(json, typeof(object));

obj._DictionaryEnthält jetzt ein Wörterbuch. Perfekt!

Dieser Code muss in Verbindung mit JSON in dynamisches C # -Objekt deserialisieren verwendet werden. + Machen Sie die Variable _dictionary im Code dort von "privat schreibgeschützt" zu öffentlich


4

Haben Sie die ExpandoObject- Klasse gesehen?

Direkt aus der MSDN-Beschreibung : "Stellt ein Objekt dar, dessen Mitglieder zur Laufzeit dynamisch hinzugefügt und entfernt werden können."

Damit können Sie Code wie folgt schreiben:

dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).Remove("Name");

Die Eigenschaftsnamen sind nicht bekannt, daher funktioniert dies nicht.
user3285954

Der Code funktioniert (ich habe ihn in Visual Studio überprüft), da die Mitarbeiterinstanz ein ExpandoObject ist, sodass zur Laufzeit Eigenschaften hinzugefügt und entfernt werden können (wie in der offiziellen MS-Dokumentation erläutert). Dieser Code erfüllt die Frage.
ADIMO

Es gibt noch andere dynamische Objekte als ExpandoObject, wie PSObject.
Felixfbecker

Nein @ADIMO nicht. Die Frage ist, wie auf die Eigenschaft eines dynamischen Objekts zugegriffen werden kann. ABER im Moment weiß er nicht, was die Eigenschaften sind. Diese kommen aus einem String-Array. Also muss er das Eigentum finden, wenn es namentlich existiert und dann den Wert von der Immobilie
erhält

4

Wenn d von Newtonsoft erstellt wurde, können Sie damit Eigenschaftsnamen und -werte lesen:

    foreach (JProperty property in d)
    {
        DoSomething(property.Name, property.Value);
    }

1

Dachte, dies könnte jemandem in der Zukunft helfen.

Wenn Sie den Eigenschaftsnamen bereits kennen, können Sie Folgendes tun:

[HttpPost]
[Route("myRoute")]
public object SomeApiControllerMethod([FromBody] dynamic args){
   var stringValue = args.MyPropertyName.ToString();
   //do something with the string value.  If this is an int, we can int.Parse it, or if it's a string, we can just use it directly.
   //some more code here....
   return stringValue;
}

Die Eigenschaftsnamen sind nicht bekannt.
user3285954

0

Sie können " dynamicObject.PropertyName.Value" verwenden, um den Wert der dynamischen Eigenschaft direkt abzurufen.

Beispiel :

d.property11.Value

1
Die Frage ist, wie man einen Wert von einem dynamischen Objekt erhält, aber er hat den Eigenschaftsnamen als Zeichenfolge ... zum Beispiel möchte er etwas tun, wie wir es in Javascript getan haben: obj ["property1"] und ich glaube, das ist kein Antworten.
Bunjeeb

0

Sie können so versuchen:

d?.property1 , d?.property2

Ich habe es getestet und arbeite mit .netcore 2.1


1
Die Frage ist, wie man einen Wert von einem dynamischen Objekt erhält, aber er hat den Eigenschaftsnamen als Zeichenfolge ... zum Beispiel möchte er etwas tun, wie wir es in Javascript getan haben: obj ["property1"] und ich glaube, das ist kein Antworten.
Bunjeeb
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.