Wie überprüfe ich, ob eine Eigenschaft für einen dynamischen anonymen Typ in c # vorhanden ist?


121

Ich habe ein anonymes Typobjekt, das ich als Dynamik von einer Methode erhalte, die ich überprüfen möchte, ob eine Eigenschaft für dieses Objekt vorhanden ist.

....
var settings = new {
                   Filename="temp.txt",
                   Size=10
}
...

function void Settings(dynamic settings) {
var exists = IsSettingExist(settings,"Filename")
}

Wie würde ich IsSettingExist implementieren?



Wenn Sie sich stark auf dynamische Objekte verlassen, lohnt es sich wahrscheinlich, sich F # - Nice Avatar übrigens
Piotr Kula

Antworten:


149
  public static bool IsPropertyExist(dynamic settings, string name)
  {
    if (settings is ExpandoObject)
      return ((IDictionary<string, object>)settings).ContainsKey(name);

    return settings.GetType().GetProperty(name) != null;
  }

  var settings = new {Filename = @"c:\temp\q.txt"};
  Console.WriteLine(IsPropertyExist(settings, "Filename"));
  Console.WriteLine(IsPropertyExist(settings, "Size"));

Ausgabe:

 True
 False

2
Dies funktioniert nicht bei dynamischen Objekten. Es wird immer null zurückgegeben.
böse

@evilom @Shikasta_Kashti Versuchen Sie, diese Methode mit einer MVC zu verwenden ViewBag? Wenn ja, siehe stackoverflow.com/a/24192518/70345
Ian Kemp

7
Echte Frage: Warum IsPropertyExist anstelle von DoesPropertyExist / HasProperty? Ist es eine Konvention, die ich nicht verstehe?
Gaspa79

@ Gaspa79. Es ist eine nicht ungewöhnliche Codierungskonvention. Einige Leute mögen ein "Is" -Präfix für alle booleschen Eigenschaften. Eine solche Konsistenz kann verhindern, dass Sie die ersten Zeichen eines Bezeichners erraten müssen (danach funktioniert Intellisense), in solchen Fällen jedoch auf Kosten eines etwas umständlichen Englisch.
löslicher Fisch

Ich finde die ungültige Verbform des IsPräfixes verwirrender, als es sonst zu verwenden wäre HasProperty. Ich würde auch sagen, dass die Verwendung eines solchen grammatikalisch falschen Präfixes in C♯ eigentlich nicht idiomatisch ist.
Ben Collins

37
public static bool HasProperty(dynamic obj, string name)
{
    Type objType = obj.GetType();

    if (objType == typeof(ExpandoObject))
    {
        return ((IDictionary<string, object>)obj).ContainsKey(name);
    }

    return objType.GetProperty(name) != null;
}

objType.GetProperty(name) != null;gibt null für Eigenschaften zurück, die existieren
Matas Vaitkevicius

3
objType.GetProperty(name) != nullwird immer ein zurückgeben bool, was (per Definition) niemals sein kann null.
Alex McMillan

@AlexMcMillan Sie sind sich nicht sicher, in welcher Dimension Sie wo Type.GetProperty(string)für eine nicht vorhandene Eigenschaft leben, und geben etwas anderes als null zurück.
Ian Kemp

2
@ IanKemp, AlexMcMillan sagte objType.GetProperty (Name)! = Null als Antwort auf MatasVaitkevicius Kommentar tatsächlich.
Sergey

15

Wenn Sie das Erstellen / Übergeben des Einstellungsobjekts steuern können, würde ich empfehlen, stattdessen ein ExpandoObject zu verwenden.

dynamic settings = new ExpandoObject();
settings.Filename = "asdf.txt";
settings.Size = 10;
...

function void Settings(dynamic settings)
{
    if ( ((IDictionary<string, object>)settings).ContainsKey("Filename") )
        .... do something ....
}

Ich kann es nicht ändern. Kann ich es auf ExpendoObject übertragen?
David MZ

6

Dies funktioniert für anonyme Typen, ExpandoObject, Nancy.DynamicDictionaryoder irgendetwas anderes, das gegossen werden kann IDictionary<string, object>.

    public static bool PropertyExists(dynamic obj, string name) {
        if (obj == null) return false;
        if (obj is IDictionary<string, object> dict) {
            return dict.ContainsKey(name);
        }
        return obj.GetType().GetProperty(name) != null;
    }

2
Tolle Lösung. Ich musste eine weitere IF-Anweisung hinzufügen, wenn ich eine JSON-Zeichenfolge in JObject konvertierte .... "if (obj ist Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name); ""
rr789

Arbeitete auch für mich. Wunderbare Antwort Seth Reno. Ich habe auch hinzugefügt "if (obj ist Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name);" in der obigen Funktion wie von rr789 vorgeschlagen. Bearbeiten Sie daher auch Ihre Antwort, um sie einzuschließen.
Brijesh Kumar Tripathi

4

Das funktioniert bei mir-:

  public static bool IsPropertyExist(dynamic dynamicObj, string property)
       {
           try
           {
               var value=dynamicObj[property].Value;
               return true;
           }
           catch (RuntimeBinderException)
           {

               return false;
           }

       }

13
Es ist keine bevorzugte Lösung, Ausnahmen zuzulassen und sie dann zu fangen, da mit dem Werfen und Fangen viel Aufwand verbunden ist. Es ist nur ein letzter Ausweg. Ausnahmen sind für für Situationen entwickelt, sollte nicht im Laufe der Ausführung wie ein Netzwerk nicht verfügbar ist geschehen. Hier gibt es viel bessere Lösungen.
Was auch immer Mann

Schlägt mit RuntimeBinderExceptionund dynamicObj[property].Value wenn der Wert tatsächlich gibt es ... var value = dynamicObj[property]ist genug ... und wenn es nicht vorhanden ist KeyNotFoundException aufDictionary geworfen wird ... siehe unten ...
Matas Vaitkevicius

Es ist keine akzeptable Lösung, Ausnahmen in der Geschäftslogik zu verwenden. 1 Klasse, 2. Semester.
Artem G

3

Keine der oben genannten Lösungen gearbeitet , dynamicdass kommt von Json, ich aber eines mit zu transformieren verwaltet Try catch(von @ user3359453) durch Ausnahmetyp (geworfen Wechsel KeyNotFoundExceptionstatt RuntimeBinderException) in etwas , das tatsächlich funktioniert ...

public static bool HasProperty(dynamic obj, string name)
    {
        try
        {
            var value = obj[name];
            return true;
        }
        catch (KeyNotFoundException)
        {
            return false;
        }
    }

Geben Sie hier die Bildbeschreibung ein

Hoffe das spart dir etwas Zeit.


1
Die Verwendung von Ausnahmen für solche Dinge wird nicht empfohlen. Hätte etwas wie Casting für JObject und Verwendung von .Property ()! = Null
Gaspa79

3

Zusammenführen und Korrigieren von Antworten von Serj-TM und user3359453, sodass es sowohl mit ExpandoObject als auch mit DynamicJsonObject funktioniert. Das funktioniert bei mir.

public static bool HasPropertyExist(dynamic settings, string name)
{
    if (settings is System.Dynamic.ExpandoObject)
        return ((IDictionary<string, object>)settings).ContainsKey(name);

    if (settings is System.Web.Helpers.DynamicJsonObject)
    try
    {
        return settings[name] != null;
    }
    catch (KeyNotFoundException)
    {
        return false;
    }


    return settings.GetType().GetProperty(name) != null;
}

2

Mit Reflektion ist dies die Funktion, die ich benutze:

public static bool doesPropertyExist(dynamic obj, string property)
{
    return ((Type)obj.GetType()).GetProperties().Where(p => p.Name.Equals(property)).Any();
}

dann..

if (doesPropertyExist(myDynamicObject, "myProperty")){
    // ...
}

1
GetProperties () listet kein dynamisches Mitglied in einem DynamicObject auf. Dafür gibt es eine spezielle Funktion GetDynamicMemberNames ().
Marco Guignard

Verwenden Sie zuerst den Lambda-Ausdruck Whereund dann Anyist er redundant, da Sie auch Ihren Filterausdruck in formulieren können Any.
Pholpar

1

Für den Fall, dass jemand ein dynamisches Objekt von Json verarbeiten muss, habe ich die Antwort von Seth Reno geändert, um dynamische Objekte zu verarbeiten, die von NewtonSoft.Json.JObjcet deserialisiert wurden.

public static bool PropertyExists(dynamic obj, string name)
    {
        if (obj == null) return false;
        if (obj is ExpandoObject)
            return ((IDictionary<string, object>)obj).ContainsKey(name);
        if (obj is IDictionary<string, object> dict1)
            return dict1.ContainsKey(name);
        if (obj is IDictionary<string, JToken> dict2)
            return dict2.ContainsKey(name);
        return obj.GetType().GetProperty(name) != null;
    }

0

Um die Antwort von @Kuroro zu erweitern, sollte unten funktionieren, wenn Sie testen müssen, ob die Eigenschaft leer ist.

public static bool PropertyExistsAndIsNotNull(dynamic obj, string name)
{
    if (obj == null) return false;
    if (obj is ExpandoObject)
    {
        if (((IDictionary<string, object>)obj).ContainsKey(name))
            return ((IDictionary<string, object>)obj)[name] != null;
        return false;
    }
    if (obj is IDictionary<string, object> dict1)
    {
        if (dict1.ContainsKey(name))
            return dict1[name] != null;
        return false;
    }
    if (obj is IDictionary<string, JToken> dict2)
    {
        if (dict2.ContainsKey(name))
            return (dict2[name].Type != JTokenType.Null && dict2[name].Type != JTokenType.Undefined);
        return false;
    }
    if (obj.GetType().GetProperty(name) != null)
        return obj.GetType().GetProperty(name).GetValue(obj) != null;
    return false;
}
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.