powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Универсальные getter и setter
17 сообщений из 17, страница 1 из 1
Универсальные getter и setter
    #38319931
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Надоело писать подобное для каждого свойства

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
public string Email
{
	get { return _customer.Email; }
	set
	{
		if (value == _customer.Email)
			return;

		_customer.Email = value;

		OnPropertyChanged("Email");
	}
}



Надоело копипастить. Решил придумать, как бы покороче. Самое простое, что пришло в голову:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
using System.ComponentModel;
using System.Reflection;

...

protected object Get(string name)
{
	return this.GetType().GetProperty(name).GetValue(this);
}

protected void Set(string name, object value)
{
	PropertyInfo pi = this.GetType().GetProperty(name);

	if (value != pi.GetValue(this))
	{
		pi.SetValue(this, value);
		OnPropertyChanged(pi.Name);
	}
}



Ну и строковые параметры имён свойств приходят через выражения (Expression), так что хардкодинга, вроде, нет, и рефакторинг спасён.

Проблема в том, что хотелось бы избежать возвращаемых и принимаемых типов object, чтобы не приходилось заниматься приведением типов. Вроде, как-то это можно через шаблоны (generics) сделать. Как? Подскажите, пожалуйста.



И ещё такой вопрос, в чём минусы такой реализации универсальных свойств? Вы как делаете - копипастите везде одинаковый по сути код для шаблонных свойств (т. е. это для вас не проблема), или что-то подобное, как у меня используете? Я пока минус вижу только в том, что в таком виде нельзя реализовать специальную логику для каждого свойства. Может, потом как-нибудь придумаю, как логику передавать в эти универсальные свойства - может, через делегаты или выражения.

Вобщем, хотелось бы мнения послушать.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38319948
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320,

использую code snippets. То есть набираешь всего одно слово и подставляется кусок кода.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38319950
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320,

Не пишите свои велосипеды. Решение уже готово.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38319969
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320
Код: sql
1.
2.
3.
4.
5.
	PropertyInfo pi = this.GetType().GetProperty(name);

	if (value != pi.GetValue(this))
	{
		pi.SetValue(this, value);


Это подходит только для простых autoimplemented propertieis. Со свойствами c backing field - уже работать не будет, хотя это самый простой случай. А свойства еще могут принимать/возвращать значения свойств агрегируемого объекта. Да и просто включать в себя некую нелинейную логику.
Вы как делаете - копипастите везде одинаковый по сути код для шаблонных свойств (т. е. это для вас не проблема), или что-то подобное, как у меня используете?
Просто вызываю PropertyChanged, передавая имя свойства через Expression<Func<T, TProperty>> - это избавляет от хардкодинга имен свойств. Для всего остального средства на все случаи жизни не придумаешь.
SolYUtor Решение уже готово.
А как у этой штуки обстоят дела со сложно устроенными свойствами? И логика вызова OnPropertyChanged тоже может быть далеко не линейной.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38319975
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

если у вас сложная логика вызова свойств, вы можете попросить Fody.PropertyChanged не переписывать свойтсво, и сделать вызов руками. Для остальных 99% случае можно использовать безбоязненно, экономит массу времени, сильно упрощает код. Распознаёт зависимости между свойствами, и делает вызовы соотвественно.
Если интересно, как оно делает - возмите dotpeek, да посмотрите результат.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38319989
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikuser7320,

использую code snippets. То есть набираешь всего одно слово и подставляется кусок кода.+1
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320033
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

IL-Weaving не используете принципиально?
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320042
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtorАлексей К,

IL-Weaving не используете принципиально?У меня основная масса сущностей генерируется через T4 по БД или WSDL. А для небольшого числа остальных случаев возможностей снипетов хватает.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320202
VIT2708
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320,

Может тебе стоит в таких случаях ОБОБЩЕННЫЕ МЕТОДЫ ИСПОЛЬЗОВАТЬ

один раз обьявил а дальше подставляешь любой тип в конструктор
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320524
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VIT2708user7320,

Может тебе стоит в таких случаях ОБОБЩЕННЫЕ МЕТОДЫ ИСПОЛЬЗОВАТЬ

один раз обьявил а дальше подставляешь любой тип в конструктор
Да, я как раз и спрашивал, как это сделать. Я обозвал это шаблонами. Я уже сделал:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
        protected T Get<T>(string name)
        {
            return (T)this.GetType().GetProperty(name).GetValue(this);
        }

        protected void Set<T>(string name, T value)
        {
            PropertyInfo pi = this.GetType().GetProperty(name);

            if (!pi.GetValue(this).Equals(value))
            {
                pi.SetValue(this, value);
                OnPropertyChanged(pi.Name);
            }
        }



Вобщем, как я понял... Поскольку этот код решает только задачу копипаста, то лучше эту задачу переложить на коллекцию сниппетов, чем засорять код. Тем более, что рефлексия накладывает свои дополнительные расходы. Все подобные "универсальные методы" на самом деле не универсальны в той или иной степени, и только добавляют сложности тем, кто с ними не знаком - видеть какие-то незнакомые атрибуты или какую-то рефлексию на простых участках, вместо обычного и простого кода... Я правильно понимаю?
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320585
Фотография Абсолют
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня чисто такой вопрос, не по теме.

У вас Cancel в диалоге редактирования EMail есть? И если да, то как реализовано возвращение предыдущих значений?
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320860
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АбсолютУ меня чисто такой вопрос, не по теме.

У вас Cancel в диалоге редактирования EMail есть? И если да, то как реализовано возвращение предыдущих значений?
Если я вас правильно понимаю, то вы говорите о том случае, когда модель представления (МП) содержит в себе объект модели (М) в качестве поля, и когда значения полей этой М изменяются при редактировании контролов представления (П), представляющих собой поля М (через привязанные свойства МП). Т. е. получается, что когда, например, контрол адреса е-мейла теряет фокус, то поле е-мейла М автоматически получает новое значение. При этом старое значение теряется и его уже не вернуть.

Ну, для этого, как я думаю (сам я такого не делал) либо организуете буферный объект, который будет хранить в себе текущую копию модели с изменениями, и по Submit копировать заменять текущий объект М буферным, либо по Cancel удалять буферный и оставлять текущую М без изменений.

Либо ещё вариант, когда у вас есть репозиторий, то буфером в этом случае является сама М. После Submit вы вызываете из репозитория Update и обновляете значение в репозитории текущей М. По Cancel - просто ничего не делаете с репозиторием, в результате у вас сохранились старые значения.

Самое же простое, изменять поля М не после потери фокуса каждым контролом, а после нажатия Submit изменять уже всю М целиком по МП с уже сделанными изменениями.

Как-то так. Вроде, элементарно?
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320869
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Самое же простое, изменять поля М не после потери фокуса каждым контролом, а после нажатия Submit изменять уже всю М целиком по МП с уже сделанными изменениями.
Только с мгновенной валидацией придётся распрощаться - только общая сводка после Submit.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320907
Фотография Абсолют
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320,

что-то как-то перебор (имо). Я от программирования слегка отошел уже, но все же помню некоторые вещи. И я все же смотрю сквозь WPF, если что.

Вот, что меня слегка смутило:
user7320get { return _customer.Email; }
set
{
if (value == _customer.Email)
return;

_customer.Email = value;

OnPropertyChanged("Email");
}


Т.е. такой подход уже подразумевает некий темп объект, который при Cancel восстановит исходное значение Email'а. Как хороший пример - реализация IEditableObject

Но почему бы сразу не сделать темповые проперти, к примеру, такие:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
private string _mail;

public string Email
{
	get { return _mail; }
	set
	{
		if (string.CompareOrdinal(value, _mail) == 0)
		{
			return;
		}

		_mail = value;

		OnPropertyChanged("Email");
	}
}



И при субмите уже сетить, в противном случае просто закрывать. Вроде я так делал в своё время. И что бы не писать по 100 раз OnPropertyChanged у меня была реализация SetPropertyAndNotifity(Expression, ref, value)
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38320919
Фотография Абсолют
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Только с мгновенной валидацией придётся распрощаться - только общая сводка после Submit.
Это не приемлемо вообще никак и никогда :)
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38321130
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторВот, что меня слегка смутило:
Это из джошесмитовского примера скопировано:




У МП есть объект М в качестве поля _customer. Свойства МП привязаны к контролам П и изменяются по потере соответствующими контролами фокуса, либо по изменению свойства. В логике МП изменение свойства МП сразу (ну, после некоторой валидации) меняет свойства лежащей в основе М. Как писал Джош Смит, МП вовсе не содержит в себе копию М, а "пробрасывает", предоставляет для МП значения свойств М. Так что если где и содержится "нетронутая" копию предыдущих данных, так это в репозитории и в лежащим под ним конкретном хранилище данных.

Нажав Cancel, мы (по сценарию примера Джоша) закрываем П сущности, одновременно уничтожается её МП и М, лежащая в основе. Точнее, не уничтожается, а становится "ненужной" (сборщик мусора и всё такое). Тогда да, данные остаются нетронутыми в репозитории.

Вообще, я сначала вас не понял, и подумал, что вы хотите реализовать сценарий, когда каждое свойство сущности редактируется по шагам - одна страница - е-мейл, вторая - имя и т. д. И вам надо, чтобы можно было нажать на Cancel и вернуться на предыдущую страницу, где должны сохраниться ранее введённые значения... Что-то типа такого. Вобщем, я перепутал. Даже в этом сценарии, пожалуй, дополнительный буферный объект не нужен.
...
Рейтинг: 0 / 0
Универсальные getter и setter
    #38321133
Фотография Абсолют
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320джошесмитовского
Да ну его. Только кровь всем портит.

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

Суть моего диалога тут - просто размышление.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Универсальные getter и setter
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]