Перевірте, чи існує властивість у класі


83

Я намагаюся дізнатися, чи існує властивість у класі, я спробував це:

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

Я не розумію, чому перший метод тесту не проходить?

[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
Не могли б ви опублікувати відповідний код MyClass?
nattyddubbs

Відповіді:


128

Ваш метод виглядає так:

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

Це додає розширення до object- базового класу всього . Коли ви викликаєте це розширення, ви передаєте його Type:

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

Ваш метод очікує екземпляра класу, а не Type. Інакше ви по суті робите

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

Тоді

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

Як правильно зазначає @PeterRitchie, на даний момент ваш код шукає власність Labelна System.Type. Ця властивість не існує.

Рішення є або

а) Надайте екземпляр MyClass для розширення:

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

б) Одягніть розширення System.Type

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

і

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

2
тобто ваш код шукає `Type.Label , not MyClass.Label`.
Пітер Річі,

Як би поставити це на розширення System. Введіть, де це можна знайти /. Куди це йде в коді для виконання?
Demodave

1
@Demodave - методи розширення просто у відкритому статичному класі. Дивіться тут для отримання додаткової інформації: msdn.microsoft.com/en-GB/library/bb383977.aspx
Jamiec 20.03.15

Якщо ви отримуєте цю помилку: "Тип не містить визначення для GetProperty", то прочитайте це: stackoverflow.com/questions/7858469/…
Тадей

27

Це відповідає на інше запитання:

Якщо ви намагаєтеся з’ясувати, чи має об’єкт (не клас) властивість,

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

повертає true, якщо (але не тільки якщо) властивість існує.

У моєму випадку я перебував у частковому поданні ASP.NET MVC і хотів щось відобразити, якщо або властивість не існувало, або властивість (логічне значення) була істинною.

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

мені тут допомогли.

Редагувати: Сьогодні, мабуть, розумно використовувати nameofоператор замість ідентифікованого імені властивості.


Що стосується використання nameofоператора, чи спрацює він (не виняток), щоб отримати назву властивості, яка може не існувати? Оскільки передумовою початкового питання було те, що ми не знаємо, чи існує ця властивість?
Zoe

Чому б вам не спробувати, а потім відредагувати мою відповідь для уточнення?
Stachu

2

Є 2 можливості.

У вас справді немає Labelвласності.

Вам потрібно викликати відповідне перевантаження GetProperty і передати правильні прапори прив'язки, наприкладBindingFlags.Public | BindingFlags.Instance

Якщо ваша власність не є загальнодоступною, вам потрібно буде використовувати BindingFlags.NonPublicабо іншу комбінацію прапорів, яка відповідає вашому випадку використання. Прочитайте посилання на документи API, щоб знайти деталі.

РЕДАГУВАТИ:

Опа, тільки помітив , що ви дзвоните GetPropertyна typeof(MyClass). typeof(MyClass)це, Typeщо точно не має Labelвластивості.


За замовчуванням використовуються прапори прив'язки Instance|Public|Static, iirc.
LukeH 11.03.13

@LukeH, я не був впевнений, тому написав "правильно" і додав "напр." :) можливо, Labelце приватна власність.
Zdeslav Vojkovic 11.03.13

1

Я отримав таку помилку: "Тип не містить визначення для GetProperty" під час прив'язки прийнятої відповіді.

Це те, з чим я закінчив:

using System.Reflection;

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

}

0

Якщо ви зобов’язуєте, як я:

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

0

Я не впевнений у контексті, чому це було потрібно, тому це може не дати вам достатньо інформації, але ось що я зміг зробити:

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

У моєму випадку я запускаю властивості із подання форми, а також використовую значення за замовчуванням, якщо запис залишено порожнім - тому мені потрібно було знати, чи є значення, яке слід використовувати - я поставив префікс до всіх своїх значень за замовчуванням у моделі за замовчуванням, тому все, що мені потрібно було перевірити, чи не було властивості, яка починалася з цього.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.