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

Как вам такое решение (нашёл в Интернете)? Какие плюсы и минусы вы видите? Есть вообще смысл так делать - "униваресальные свойства" и т. п.?

Тут, значит, штука в том, что есть универсальный сеттер и эта новая штука - атрибут CallerMemberName. Плюс в том, что нет жёстко заданных строк в имени propertyName, нет медленной рефлексии, нет выражений - всё это требовалось в разных реализациях, уводящих от жёстко заданных строк. Если только реализация CallerMemberName сама по себе не медленная, то всё вообще замечательно.


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
public class Base : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
    {
        if (!EqualityComparer<T>.Default.Equals(field, value))
        {
            field = value;
            OnPropertyChanged(propertyName);
        }
    }
}


// Использование.

public MyClass : Base
{
    private string _myField;
    public string MyProperty
    {
        get { return _myField; }
        set { this.SetProperty<string>(ref _myField, value); }
    }
}
...
Рейтинг: 0 / 0
Универсальный setter
    #38531064
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя в Постшарпе выглядит лучше ...
...
Рейтинг: 0 / 0
Универсальный setter
    #38531092
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да-да... уличная магия...
user7320Хотя в Постшарпе...
Хм... уличная магия...
user7320нашёл в Интернете... нет медленной рефлексии...
Ну а вообще, в данном случае, домотканный код... лично мне симпатичнее непрозрачного посташрпа :) Хоть там оно и выглядит лучше :)
...
Рейтинг: 0 / 0
Универсальный setter
    #38531114
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Есть вообще смысл так делать - "универсальные свойства" и т. п.?
Я считаю, что нет.

Подумайте о тех, кто будет поддерживать. Поставит кто-нибудь брейкпойнт в этом свойстве - и будет 30 раз тыкать, пока нужное пройдет.
Сейчас я такими вот вещами занимаюсь.
Наабстрагировали и науниверсилизировали настолько, что на перемещение иконки на 20 пикселей дают 4 дня.
И почти хватает!
...
Рейтинг: 0 / 0
Универсальный setter
    #38531118
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129user7320Есть вообще смысл так делать - "универсальные свойства" и т. п.?
Я считаю, что нет.

Подумайте о тех, кто будет поддерживать. Поставит кто-нибудь брейкпойнт в этом свойстве - и будет 30 раз тыкать, пока нужное пройдет.
Сейчас я такими вот вещами занимаюсь.
Наабстрагировали и науниверсилизировали настолько, что на перемещение иконки на 20 пикселей дают 4 дня.
И почти хватает!
Ну да, согласен - уже надо разбираться в чужом говнокоде. Но иногда лучше заставить одного бедолагу-новичка разбираться, чем всю команду - быдлокодить спагетти и ронять командный дух. Реально достаёт в каждом сеттере делать

1) проверку на null,
2) проверку на равество и
3) вызов оповещения изменения свойства.

Это как минимум.

buserДа-да... уличная магия...
user7320Хотя в Постшарпе...
Хм... уличная магия...
user7320нашёл в Интернете... нет медленной рефлексии...
Ну а вообще, в данном случае, домотканный код... лично мне симпатичнее непрозрачного посташрпа :) Хоть там оно и выглядит лучше :)
В смысле "уличная магия"? Если что, я и не считаю, что написал что-то супер-пупер. Я вообще просто передрал.

А что, в Постшарпе никто не знает, как оно всё работает? )))
...
Рейтинг: 0 / 0
Универсальный setter
    #38531126
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320, ну постшарп инжектит свой код... если я не ошибаюсь... хотя... иногда это удобно... не засерается основная логика и т.п. ... ну и про ваш восторг по поводу неиспользования рефлексии в случае с универсальным сеттером использующим атрибуты [CallerMemberXXX] мне кажется необоснованным :)
...
Рейтинг: 0 / 0
Универсальный setter
    #38531153
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
buseruser7320, ну постшарп инжектит свой код... если я не ошибаюсь... хотя... иногда это удобно... не засерается основная логика и т.п. ... ну и про ваш восторг по поводу неиспользования рефлексии в случае с универсальным сеттером использующим атрибуты [CallerMemberXXX] мне кажется необоснованным :)
Так это ж дотнетовский атрибут - может, там всякие липперты и Ко на ассемблере всё заоптимизировали? )))
...
Рейтинг: 0 / 0
Универсальный setter
    #38531174
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320, реализация интерфейса INotifyPropertyChanged потребует ручного указания имени свойства которое было изменено и проверку перед присвоением. Данная реализация позволяет от этого избавиться. Следовательно есть смысл её применять.

Возможный недостаток это наличие дополнительного вызова SetProperty в каждом свойстве. Можно добавить атрибут [MethodImplAttribute(MethodImplOptions.AggressiveInlining)].

Еще вопрос насколько эффективно использование EqualityComparer. Если бы у нас были только ссылочные типы, то можно было бы использовать Object.Equals(obj1, obj2), но метод должен работать и с value типами. Как вариант можно написать общий метод для ссылочных типов и конкретные методы для value типов. Примерно так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
protected void SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
	where T : class
{
   if (!Equals(field, value))
   {
       field = value;
       OnPropertyChanged(propertyName);
   }
}

protected void SetProperty(ref int field, int value, [CallerMemberName] string propertyName = "")
{
   if (field != value)
   {
       field = value;
       OnPropertyChanged(propertyName);
   }
}

// ... и так далее для других value типов


Будет ли от этого выигрыш - вопрос :)

Решение с PostSharp безусловно самое красивое, но его есть смысл использовать только если в проекте уже используется PostSharp. Ставить его только ради NotifyPropertyChanged это как из пушки по воробьям.


D129Подумайте о тех, кто будет поддерживать. Поставит кто-нибудь брейкпойнт в этом свойстве - и будет 30 раз тыкать, пока нужное пройдет.
Не вижу проблемы в данном случае. Свойство продолжают оставиться независимыми так что ставь брейкпойнт ровно в том свйостве которое тебе нужно. Если ты говорил о методах SetProperty и OnPropertyChanged, то там помогут условные точки останова.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531331
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileЕще вопрос насколько эффективно использование EqualityComparer. Если бы у нас были только ссылочные типы, то можно было бы использовать Object.Equals(obj1, obj2), но метод должен работать и с value типами. Как вариант можно написать общий метод для ссылочных типов и конкретные методы для value типов. Примерно так:
...
Будет ли от этого выигрыш - вопрос :)
Я думал над этим. Я, конечно, не спец в низкоуровневых штуках, но по-моему, проверка двух, например, числовых переменных на равенство и присвоение одной числовой переменно того же значения, что уже у неё есть - примерно одного порядка сложности операции. Может, даже присвоение быстрее. А вот для ссылочных типов проверка как раз нужна - они более громоздкие.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531337
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Используй Code Snippets для написания свойств. Используй Expression для указания имени свойства в оповещении об изменении, если производительность позволяет. Всё остальное лишнее.

Базовый класс.
Парсер Expression .

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
    public class ClassifierItem : NotificationObject 
    { 
        public int? ID 
        { 
            get { return _ID; } 
            set
            { 
                _ID = value; 
                OnPropertyChanged(() => ID); 
            } 
        } 
        int? _ID; 
    }
...
Рейтинг: 0 / 0
Универсальный setter
    #38531340
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320нет медленной рефлексииРефлексию можно ускорить используя Emit или Expression. Вот пример "ускорителя" через Expression.
Код: c#
1.
2.
3.
4.
var obj = new MyClass();
var myProperty = FastPropertyFactory.Create(typeof(MyClass), "MyProperty");

var v = myProperty.GetValue(obj);
...
Рейтинг: 0 / 0
Универсальный setter
    #38531343
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я на данный момент использую свою модификацию вот этого решения . Рефлекшн применяется только при создании экземпляра модели, прочие вызовы используют expressions, и отсутствуют backing fields - в них просто нет надобности. Плюс декларативное описание зависимостей между свойствами и командами (я в своем варианте сделал разбор всего дерева зависимостей - т.е. если свойства B зависит от свойства А, а команда С зависит от свойства В, то при изменении свойства А команда С обязательно просмотрит изменения свойства В).
...
Рейтинг: 0 / 0
Универсальный setter
    #38531346
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кuser7320Используй Code Snippets для написания свойств. Используй Expression для указания имени свойства в оповещении об изменении, если производительность позволяет. Всё остальное лишнее.

Базовый класс.
Парсер Expression .

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
    public class ClassifierItem : NotificationObject 
    { 
        public int? ID 
        { 
            get { return _ID; } 
            set
            { 
                _ID = value; 
                OnPropertyChanged(() => ID); 
            } 
        } 
        int? _ID; 
    }


1. У вас в сеттере нет проверки на равенство.
2. Разборщик выражений разбирает только выражения доступа к полю или свойству - т. е. ваш код полезен только в выражениях, используемых для реализации INotifyPropertyCHanged и т. п., где не надо, например, получать имя вызывающего метода или события и т. п. Для более унифицированного использования таких вещей я делал портянку из кейсов

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
public static string GetMemberName<TResult>(Expression<Func<T, TResult>> expression, ExpressionType expressionType)
{
    switch (expressionType)
    {
        case ExpressionType.MemberAccess:
            var memberExpression = (MemberExpression)expression.Body;
            if (memberExpression == null)
            {
                throw new InvalidOperationException("Expression must be of member access.");
            }
            return memberExpression.Member.Name;

        case ExpressionType.Call:
            var methodCallExpression = expression.Body as MethodCallExpression;
            if (methodCallExpression == null)
            {
                throw new InvalidOperationException("Expression must be of method access.");
            }
            return methodCallExpression.Method.Name;

        default:
            throw new InvalidOperationException("No appropriate expression was passed.");
    }
}



А выражения я и так использовал уже давно. Но решил уйти от них. Выражения нужны были из-за недостатка самого фреймворка - там всякие стэк трейсы, жёстко заданные строки и прочие костыли. Если теперь есть атрибут CallerMemberName - зачем выражения - все эти портянки костылей? Кроме того, CallerMemberName позволяет воспользоваться и старыми наработками из выражений - он же реализован в виде необязательного параметра, т. е. можно и свои значения имени передавать.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531348
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

а про сниппеты спасибо, что напомнили. Я про них всегда забываю. По идее, вы в чём-то правы - программные решения, не решающие конкретных задач (т. е. тех, над которыми вы работаете в данном проекте), а решающие задачи удобства написания кода, не должны смешиваться с логикой приложения, а должны выноситься в логику среды разработки. Потому что за удобство написания кода вашего приложения отвечает не ваше приложение, а среда разработки.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531359
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user73201. У вас в сеттере нет проверки на равенство.А так ли она нужна? Я обычно её делаю, только если она действительно нужна. А если делать универсальный механизм тут возникают вопросы какой компаратор использовать, например, в случае со строками.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531389
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user73202. Разборщик выражений разбирает только выражения доступа к полю или свойству - т. е. ваш код полезен только в выражениях, используемых для реализации INotifyPropertyCHanged и т. п., где не надо, например, получать имя вызывающего метода или события и т. п.Он ещё умеет формировать "путь к свойству", где-то это было надо, например:
Код: c#
1.
var path = PropertyPathExpressionParser.GetPropertyPath(() => P1.P2.P3);

Ну а так - да, он предназначен в основном для реализации INotifyPropertyChanged, на универсальность не претендует.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531447
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazile Если ты говорил о методах SetProperty и OnPropertyChanged, то там помогут условные точки останова.
Очень помогут, если ты знаешь, что поставить как условие. А если как раз нет?
А если уже знаешь, что ожидать в точке останова, то уже не надо и дебагировать....

Код надо писать, а не изголяться. Ну сколько у вас свойств - 50? 150?
При любом изменении не-автор вашего решения - да еще в условиях прессинга (а так бывает)
просто допишет свое, и не будет пользоваться вашей высокохудожественной поделкой.
А вдруг - подумает каждый, кто не знаком лично с вами - этот код еще что-то вызывает, а мне это не нужно.
:-/

:-)

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

"В условиях прессинга" - это всё же не нормальный процесс разработки ПО. А то говнокод получается чаще в условиях именно прессинга, а потом уже когда "кто-то слишком много архитектурой балуется".

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

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

Модные дизайнеры лишили в частности меня даже компилятора - если хочешь понять, кто вызывает конкретную функцию - то Студия показывает что никто. :-) Все поставляется через интерфейсы и конфигурационные связки.

Меня уже трясет, когда я вижу очередной интерфейс с одним методом.

При дебаггировании приходится ставить брейкпойнты наугад, иногда во всех методах класса, и если еще к этому добавить условный останов - когда вообще непонятно, что должно и куда прийти - аджайл же, нету никакой документации - то....
Говорю "большое спасибо" каждому ленивому умнику.
:-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38531599
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129user7320 Там всего-то три строчки.

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

Модные дизайнеры лишили в частности меня даже компилятора - если хочешь понять, кто вызывает конкретную функцию - то Студия показывает что никто. :-) Все поставляется через интерфейсы и конфигурационные связки.

Меня уже трясет, когда я вижу очередной интерфейс с одним методом.

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

А вы это, свой продукт поддерживаете, или пытаетесь чужой код дебажить? Если чужой - то, может, от вас специально всё скрывают? С такими аджайлами и абстракциями и обфускации не нужны.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531606
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129,

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

А вы это, свой продукт поддерживаете, или пытаетесь чужой код дебажить? Если чужой - то, может, от вас специально всё скрывают? С такими аджайлами и абстракциями и обфускации не нужны.

А я и есть разработчик. Но удивлять не могу. Слишком тупой для этого. Мой код прост и понятен - я два года писал модуль практически один, и когда уволился - мне от туда ни разу не позвонили. Значит разобрались без меня.

Обфускации не нужны, потому, что клиент штучный.
Правда, очень большой и богатый.
Украсть программу для супермаркета можно только вместе с самим супермаркетом.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531629
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320D129,

а зачем дебажить? Всё же на юнит-тестах делается. Тупо меняешь код, пока тесты не начнут проходить. Дебажить даже не надо.
О, это то еще же горе..... Юнит тесты в бизнес-приложениях - это жупел.
Проверка того, а работает ли поиск в классе List<> ?
Ура! Работает! AssertTrue!!!

бррр...
...
Рейтинг: 0 / 0
Универсальный setter
    #38531660
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320а зачем дебажить? Всё же на юнит-тестах делается. Тупо меняешь код, пока тесты не начнут проходить. Дебажить даже не надо.
У тебя какое-то наивное представление о процессе разработки. Даже если код на 100% покрыт юнит-тестами, то все равно без отладки не получится обойтись. Не говорят уже о том что 100% покрытие встречается не так часто.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531662
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129О, это то еще же горе..... Юнит тесты в бизнес-приложениях - это жупел.
Проверка того, а работает ли поиск в классе List<> ?
Ура! Работает! AssertTrue!!!
бррр...
В самом деле "бррр.". Только это не вина юнит-тестов, а разработчика не понимающего что нужно тестировать, а что нет.
...
Рейтинг: 0 / 0
25 сообщений из 65, страница 1 из 3
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Универсальный setter
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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