Überprüfen Sie, ob eine Eigenschaft in einer Klasse vorhanden ist

83

Ich versuche zu wissen, ob eine Eigenschaft in einer Klasse vorhanden ist. Ich habe Folgendes versucht:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

Ich verstehe nicht, warum die erste Testmethode nicht besteht?

[TestMethod]
public void Test_HasProperty_True()
{
    var res = typeof(MyClass).HasProperty("Label");
    Assert.IsTrue(res);
}

[TestMethod]
public void Test_HasProperty_False()
{
    var res = typeof(MyClass).HasProperty("Lab");
    Assert.IsFalse(res);
}
Kris-I
quelle
4
Würde es Ihnen etwas ausmachen, den entsprechenden Code von zu veröffentlichen MyClass?
Nattyddubbs

Antworten:

127

Ihre Methode sieht folgendermaßen aus:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

Dies fügt eine Erweiterung hinzu object- die Basisklasse von allem . Wenn Sie diese Nebenstelle aufrufen, übergeben Sie sie Type:

var res = typeof(MyClass).HasProperty("Label");

Ihre Methode erwartet eine Instanz einer Klasse, keine Type. Ansonsten machst du im Wesentlichen

typeof(MyClass) - this gives an instanceof `System.Type`. 

Dann

type.GetType() - this gives `System.Type`
Getproperty('xxx') - whatever you provide as xxx is unlikely to be on `System.Type`

Wie @PeterRitchie richtig hervorhebt, sucht Ihr Code an dieser Stelle nach einer Eigenschaft Labelfür System.Type. Diese Eigenschaft existiert nicht.

Die Lösung ist entweder

a) Stellen Sie der Erweiterung eine Instanz von MyClass bereit:

var myInstance = new MyClass()
myInstance.HasProperty("Label")

b) Setzen Sie die Verlängerung auf System.Type

public static bool HasProperty(this Type obj, string propertyName)
{
    return obj.GetProperty(propertyName) != null;
}

und

typeof(MyClass).HasProperty("Label");
Jamiec
quelle
2
dh Ihr Code sucht nach "Type.Label , not MyClass.Label".
Peter Ritchie
Wie würde man dies auf die Erweiterung System.Type setzen, wo würde das gefunden werden /. Wohin geht dies im auszuführenden Code?
Demodave
1
@ Demodave - Erweiterungsmethoden befinden sich nur in einer öffentlichen statischen Klasse. Weitere Informationen finden Sie hier: msdn.microsoft.com/en-GB/library/bb383977.aspx
Jamiec
Wenn Sie diese Fehlermeldung erhalten: "Typ enthält keine Definition für GetProperty", lesen Sie diese: stackoverflow.com/questions/7858469/…
Tadej
27

Dies beantwortet eine andere Frage:

Wenn Sie herausfinden möchten, ob ein OBJEKT (keine Klasse) eine Eigenschaft hat,

OBJECT.GetType().GetProperty("PROPERTY") != null

Gibt true zurück, wenn (aber nicht nur wenn) die Eigenschaft vorhanden ist.

In meinem Fall befand ich mich in einer ASP.NET MVC-Teilansicht und wollte etwas rendern, wenn entweder die Eigenschaft nicht vorhanden war oder die Eigenschaft (boolesch) wahr war.

@if ((Model.GetType().GetProperty("AddTimeoffBlackouts") == null) ||
        Model.AddTimeoffBlackouts)

hat mir hier geholfen.

Bearbeiten: Heutzutage ist es wahrscheinlich klug, den nameofOperator anstelle des String-Eigenschaftsnamens zu verwenden.

Stachu
quelle
Funktioniert es in Bezug auf die Verwendung des nameofOperators (ohne Ausnahme), den Namen einer Eigenschaft abzurufen, die möglicherweise nicht vorhanden ist? Da die Prämisse der ursprünglichen Frage lautete, dass wir nicht wissen, ob diese Eigenschaft existiert?
Zoe
Warum versuchst du es nicht und bearbeitest dann meine Antwort, um es zu klären?
Stachu
2

Es gibt 2 Möglichkeiten.

Sie haben wirklich kein LabelEigentum.

Sie müssen die entsprechende GetProperty-Überladung aufrufen und die richtigen Bindungsflags übergeben, zBindingFlags.Public | BindingFlags.Instance

Wenn Ihre Immobilie nicht öffentlich ist, müssen Sie eine BindingFlags.NonPublicandere Kombination von Flags verwenden, die zu Ihrem Anwendungsfall passt. Lesen Sie die referenzierten API-Dokumente, um die Details zu finden.

BEARBEITEN:

Ooops, nur bemerkt , dass Sie rufen GetPropertyauf typeof(MyClass). typeof(MyClass)ist Typewas sicher kein Labeleigentum hat.

Zdeslav Vojkovic
quelle
Die standardmäßig verwendeten Bindungsflags sind Instance|Public|Staticiirc.
LukeH
@ LukeH, ich war mir nicht sicher, also schrieb ich 'richtig' und fügte 'zB' hinzu :) Vielleicht Labelist das Privateigentum.
Zdeslav Vojkovic
1

Ich habe folgende Fehlermeldung erhalten: "Typ enthält keine Definition für GetProperty" beim Verknüpfen der akzeptierten Antwort.

Das ist, was ich am Ende hatte:

using System.Reflection;

if (productModel.GetType().GetTypeInfo().GetDeclaredProperty(propertyName) != null)
{

}
Tadej
quelle
0

Wenn Sie so verbindlich sind wie ich:

<%# Container.DataItem.GetType().GetProperty("Property1") != null ? DataBinder.Eval(Container.DataItem, "Property1") : DataBinder.Eval(Container.DataItem, "Property2")  %>
Ben
quelle
0

Ich bin mir nicht sicher, warum dies erforderlich war. Daher werden möglicherweise nicht genügend Informationen für Sie zurückgegeben, aber ich konnte Folgendes tun:

if(typeof(ModelName).GetProperty("Name of Property") != null)
{
//whatevver you were wanting to do.
}

In meinem Fall durchlaufe ich Eigenschaften aus einer Formularübermittlung und habe auch Standardwerte zu verwenden, wenn der Eintrag leer gelassen wird. Daher musste ich wissen, ob ein Wert zu verwenden war. Ich habe allen meinen Standardwerten im Modell ein Präfix vorangestellt Mit Standard musste ich also nur überprüfen, ob es eine Eigenschaft gab, die damit begann.

C Gil
quelle