Получить имя свойства класса

У меня есть приложение winform, собирающее данные с помощью привязки данных. Все выглядит нормально, за исключением того, что мне нужно связать имущество с текст, используя строку:

Me.TextEdit4.DataBindings.Add(New System.Windows.Forms.Binding("EditValue", Me.MyClassBindingSource, "MyClassProperty", True))

Это нормально работает, но если я изменю имя свойства класса, компилятор, очевидно, не предупредит меня.

Я хотел бы получить имя свойства путем отражения, но я не знаю, как указать имя свойства, которое я хочу (я знаю только, как перебирать все свойства класса)

Любая идея?

Просто чтобы убедиться: вы хотите получить свойство по имени, но имя могло измениться? Это звучит как что-то не решаемое ...

EggyBach 30.09.2008 12:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
1
7 362
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

По иронии судьбы, отражение ожидает, что вы предоставите имя свойства, чтобы получить его информацию :)

Вы можете создать собственный атрибут, применить его к желаемому свойству. Тогда вы сможете просто получить имя свойства, имеющего этот атрибут.

У вас возникнет такая же проблема с использованием отражения, потому что для того, чтобы найти нужное свойство во всех свойствах типа, вам нужно знать его имя, верно?

Вы можете отразить Тип, но вы не можете отразить его членов, кроме как по имени.

Если бы это было единственное свойство или вы точно знали порядок, вы могли бы найти его по индексу, но, вообще говоря, самый безопасный путь - это строка.

Я считаю, что изменение имени вызовет исключение во время выполнения, но я не уверен на 100%, в любом случае это, вероятно, лучшая возможность.

Предполагая, что исключение не возникает автоматически, вы можете добавить Debug.Assert, который проверяет, существует ли свойство с таким именем, но опять же, это только время выполнения.

1) Укажите точное имя свойства, которое вы хотите, и оставьте его таким же.

2) Напишите тест с использованием этого имени свойства.

Ответ принят как подходящий

Вот пример того, о чем я говорю:

[AttributeUsage(AttributeTargets.Property)]
class TextProperyAttribute: Attribute
{}

class MyTextBox
{
    [TextPropery]
    public string Text { get; set;}
    public int Foo { get; set;}
    public double Bar { get; set;}
}


static string GetTextProperty(Type type)
{
    foreach (PropertyInfo info in type.GetProperties())
    {
        if (info.GetCustomAttributes(typeof(TextProperyAttribute), true).Length > 0)
        {
            return info.Name;
        }
    }

    return null;
}

...

Type type = typeof (MyTextBox);

string name = GetTextProperty(type);

Console.WriteLine(name); // Prints "Text"

Блин, ты меня опередил… Я собирался опубликовать пример. : - /

Konrad Rudolph 30.09.2008 12:49

Могу добавить, что текстуально почти то же самое.

Konrad Rudolph 30.09.2008 12:50

Конрад Рудольф, сегодня я потерял ~ 200 репутации по неизвестной причине, дайте шанс :). Проголосуйте за это!

aku 30.09.2008 12:50

Но если я правильно понимаю, мне понадобится один класс и один метод для каждого свойства: FooPropertyAttribute и GetFooProperty, BarPropertyAttribute и GetBarAttribute. Это верно?

Mat 30.09.2008 17:36

MiguelE, нет, вам понадобится 1 атрибут, чтобы пометить привязываемое свойство. Если вам нужна дополнительная информация, вы можете сохранить ее в этом атрибуте.

aku 30.09.2008 17:43

Я все еще не понимаю. Не могли бы вы предоставить образец того, как получить все три имени свойств класса в образце кода (Text, Foo и Bar)?

Gaius 01.10.2008 13:29

MiguelE, может быть завтра, сегодня я немного устал.

aku 01.10.2008 14:21

Если вы используете C# 3.0, есть способ получить имя свойства динамически, без жесткого программирования.

private string GetPropertyName<TValue>(Expression<Func<BindingSourceType, TValue>> propertySelector)
{
    var memberExpression = propertySelector.Body as MemberExpression;
    return memberExpression != null 
           ? memberExpression.Member.Name 
           : string.empty;
}

Где BindingSourceType - это имя класса вашего экземпляра объекта источника данных.

Затем вы можете использовать лямбда-выражение для выбора свойства, которое вы хотите привязать, строго типизированным способом:

this.textBox.DataBindings.Add(GetPropertyName(o => o.MyClassProperty),
                              this.myDataSourceObject,
                              "Text");

Это позволит вам безопасно реорганизовать код, не нарушая все ваши привязки данных. Но с точки зрения производительности использование деревьев выражений аналогично использованию отражения.

Предыдущий код довольно уродлив и не отмечен, но идею вы поняли.

Приятно, но это создает зависимость компиляции между пользовательским интерфейсом и объектом источника данных.

aku 30.09.2008 12:59

Это не должно быть проблемой ... Я не уверен, что понимаю, почему пользовательский интерфейс не должен знать тип отображаемых объектов. В MVP / MVC это почти всегда так, даже если мы используем модель представления. Но да, если вы не можете знать тип объекта, вы не можете использовать это решение.

Romain Verdier 30.09.2008 13:06

Я согласен, что строгий набор текста - это хорошо. Однако привязка данных обычно основана на текстовых именах. Обычно вы настраиваете через какой-то графический интерфейс или в файле конфигурации (например, XAML). Хотя ваше решение очень крутое!

aku 30.09.2008 13:08

Похоже, что здесь задающему вопрос нужно синхронизировать строки, используемые для ссылки на имена свойств и имена свойств. Он явно знает, какой предмет связывает :)

Romain Verdier 30.09.2008 13:17

Компилятор VB создает лямбда-выражение с дополнительным уровнем, поэтому эквивалент VB должен получить UnaryExpression из propertySelector.Body, а затем получить MemberExpression из unary.Operand.

Jason Stangroome 30.09.2008 13:36

Очень красивое решение. Мне все еще нужно думать о лямбда-выражениях, но я вижу красоту этого подхода. Недурно!

Eggs McLaren 30.09.2008 17:38

Другие вопросы по теме