Sprawdź, czy właściwość istnieje w klasie


83

Próbuję wiedzieć, czy właściwość istnieje w klasie, próbowałem tego:

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

Nie rozumiem, dlaczego pierwsza metoda testu nie przechodzi?

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

4
Czy możesz wysłać odpowiedni kod z MyClass?
nattyddubbs

Odpowiedzi:


128

Twoja metoda wygląda następująco:

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

To dodaje rozszerzenie do object- klasy bazowej wszystkiego . Kiedy dzwonisz na to rozszerzenie, mijasz je Type:

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

Twoja metoda oczekuje wystąpienia klasy, a nie Type. W przeciwnym razie zasadniczo to robisz

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

Następnie

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

Jak słusznie zauważa @PeterRitchie, w tym momencie Twój kod szuka właściwości Labelna System.Type. Ta nieruchomość nie istnieje.

Rozwiązanie jest albo

a) Podaj wystąpienie MyClass do rozszerzenia:

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

b) Załóż przedłużenie System.Type

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

i

typeof(MyClass).HasProperty("Label");

2
tzn. twój kod szuka „Type.Label MyClass.Label” , not .
Peter Ritchie

Jak można to umieścić w rozszerzeniu System.Type, gdzie można by znaleźć /. Gdzie to się znajduje w kodzie do wykonania?
Demodave

1
@Demodave - metody rozszerzające znajdują się tylko w publicznej klasie statycznej. Więcej informacji znajdziesz tutaj: msdn.microsoft.com/en-GB/library/bb383977.aspx
Jamiec

Jeśli pojawi się ten błąd: „Typ nie zawiera definicji dla GetProperty”, przeczytaj to: stackoverflow.com/questions/7858469/ ...
Tadej

27

To odpowiada na inne pytanie:

Jeśli próbujesz dowiedzieć się, czy OBIEKT (nie klasa) ma właściwość,

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

zwraca prawdę, jeśli (ale nie tylko jeśli) właściwość istnieje.

W moim przypadku byłem w widoku częściowym ASP.NET MVC i chciałem wyrenderować coś, jeśli właściwość nie istnieje lub właściwość (wartość logiczna) jest prawdziwa.

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

pomogło mi tutaj.

Edycja: w dzisiejszych czasach prawdopodobnie nameofsprytnie jest użyć operatora zamiast nazwy właściwości ze strunami.


Jeśli chodzi o użycie nameofoperatora, czy zadziała (nie zgłosi wyjątek), aby uzyskać nazwę właściwości, która może nie istnieć? Skoro przesłanką pierwotnego pytania było to, że nie wiemy, czy ta nieruchomość istnieje?
Zoe

Dlaczego nie spróbujesz, a potem nie zredagujesz mojej odpowiedzi, aby wyjaśnić?
Stachu

2

Istnieją 2 możliwości.

Naprawdę nie masz Label własności.

Musisz wywołać odpowiednie przeciążenie GetProperty i przekazać odpowiednie flagi powiązania, npBindingFlags.Public | BindingFlags.Instance

Jeśli Twoja nieruchomość nie jest publiczna, będziesz musiał użyć BindingFlags.NonPublic lub innej kombinacji flag, która pasuje do twojego przypadku użycia. Przeczytaj dokumentację interfejsu API, do którego się odwołujesz, aby znaleźć szczegółowe informacje.

EDYTOWAĆ:

Ojej, Właśnie zauważyłem zadzwonić GetPropertyna typeof(MyClass). typeof(MyClass)Jest Typektóre na pewno nie ma Labelwłasności.


Domyślne używane flagi Instance|Public|Staticpowiązań to iirc.
LukeH

@LukeH, nie byłem pewien, więc napisałem „poprawne” i dodałem „np.” :) może Labeljest to własność prywatna.
Zdeslav Vojkovic

1

Otrzymałem ten błąd: „Typ nie zawiera definicji dla GetProperty” podczas wiązania zaakceptowanej odpowiedzi.

Oto, co otrzymałem:

using System.Reflection;

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

}

0

Jeśli jesteś wiążący tak jak ja:

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

0

Nie jestem pewien kontekstu, dlaczego było to potrzebne, więc może to nie zwrócić wystarczającej ilości informacji, ale oto, co udało mi się zrobić:

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

W moim przypadku przeglądam właściwości z przesłania formularza, a także mam wartości domyślne do użycia, jeśli wpis jest pusty - więc musiałem wiedzieć, czy istnieje wartość do użycia - przedrostkiem wszystkie moje wartości domyślne w modelu z Default, więc wszystko, co musiałem zrobić, to sprawdzić, czy istnieje właściwość, która zaczęła się od tego.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.