powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Универсальный setter
65 сообщений из 65, показаны все 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
Универсальный setter
    #38531689
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

ну в данном случае expression вряд ли будет быстрее рефлекшена. Если собрать через него выражение аналогичное рефлекшену и закешировать тогда да.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531690
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileuser7320а зачем дебажить? Всё же на юнит-тестах делается. Тупо меняешь код, пока тесты не начнут проходить. Дебажить даже не надо.
У тебя какое-то наивное представление о процессе разработки. Даже если код на 100% покрыт юнит-тестами, то все равно без отладки не получится обойтись. Не говорят уже о том что 100% покрытие встречается не так часто.
А сами тесты надо дебажить?
...
Рейтинг: 0 / 0
Универсальный setter
    #38531691
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей К,

а переписать свою библиотеку через CallerMemberName пробовали? Может, там всё ужмётся в разы.
...
Рейтинг: 0 / 0
Универсальный setter
    #38531692
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanАлексей К,

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

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

а переписать свою библиотеку через CallerMemberName пробовали? Может, там всё ужмётся в разы.Оно под 4.5, а мне под 4.0 надо. :-(
...
Рейтинг: 0 / 0
Универсальный setter
    #38531704
netivan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КnetivanАлексей К,

ну в данном случае expression вряд ли будет быстрее рефлекшена. Если собрать через него выражение аналогичное рефлекшену и закешировать тогда да.Ну я и предложил с оговоркой, что если производительность позволяет. А она скорее всего позволяет, это же отображение данных, их при отображении обычно много не бывает.
ну понятно, хотя вдруг обновление грида 1 млн в секунду, вот там будет заметно. Да и вообще можно и string передавать, ничего криминального не вижу тут.Раздули из такой фигни целую тему)
...
Рейтинг: 0 / 0
Универсальный setter
    #38531718
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
netivanну понятно, хотя вдруг обновление грида 1 млн в секунду, вот там будет заметно.Уверен, там тонкое место будет в другом месте. :-)
netivanДа и вообще можно и string передавать, ничего криминального не вижу тут.Если будет ошибка в имени свойства - её будет непросто отловить. С Expression как-то спокойнее. :-)
netivanРаздули из такой фигни целую тему)Я узнал про CallerMemberName, значит не зря. :-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38531941
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Алексей К,

а переписать свою библиотеку через CallerMemberName пробовали? Может, там всё ужмётся в разы.
Вряд ли в разы - это решение решает только проблему вызова PropertyChanged, backing fields и логика оповещения зависимостей будет всё так же присутствовать. Решение по ссылке, которую я постил на предыдущей странице, действительно ощутимо сжимает код (базовый класс модели получился достаточно объемным). Единственное "но" этого решения - строчные именования свойств в атрибуте описания зависимости, но это решается рантаймовой проверко в конструкторе.
...
Рейтинг: 0 / 0
Универсальный setter
    #38532090
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileчто нужно тестировать, а что нет.
Ну это вообще я поприкалывался раз - на заседации.
Купили "Ковертюру" - это для джавы такая утилита, которая как раз замеряет покрытие юнит-тестами.
(этож еще деньги на этом зарабатывают!!! )

И она дает 25%. Полно кода, где юнит тестить просто нечего. То есть, абсолютно.
А обсуждался вопрос, как пометить едиообразно те методы, которая Кю вертюра брать в рассчет не должна.

А я им рассказал случай, из геологической практики моих родителей -
Когда некий руководитель получил от буровиков соц. обязательства - обеспечить выход керна 78%.
Начал возмущаться - как это 78%!!! Вся страна берет повышенные обязательства - 106% , даже 110%!!! А вы только 78!!!!
Не менее 103 должно быть!

Я им и сказал - что не надо насиловать инструмент, то, что данный тип аппликации покрыт на 25% - это научный факт.
Норма. Изменится тип проэкта - изменится и цифра. Незачем вносить в код то, что не код.

:-)))
...
Рейтинг: 0 / 0
Универсальный setter
    #38532110
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129bazileчто нужно тестировать, а что нет.
Ну это вообще я поприкалывался раз - на заседации.
Купили "Ковертюру" - это для джавы такая утилита, которая как раз замеряет покрытие юнит-тестами.
(этож еще деньги на этом зарабатывают!!! )

И она дает 25%. Полно кода, где юнит тестить просто нечего. То есть, абсолютно.
А обсуждался вопрос, как пометить едиообразно те методы, которая Кю вертюра брать в рассчет не должна.

А я им рассказал случай, из геологической практики моих родителей -
Когда некий руководитель получил от буровиков соц. обязательства - обеспечить выход керна 78%.
Начал возмущаться - как это 78%!!! Вся страна берет повышенные обязательства - 106% , даже 110%!!! А вы только 78!!!!
Не менее 103 должно быть!

Я им и сказал - что не надо насиловать инструмент, то, что данный тип аппликации покрыт на 25% - это научный факт.
Норма. Изменится тип проэкта - изменится и цифра. Незачем вносить в код то, что не код.

:-)))
Ваши проблемы от того, что у ваших заказчиков до... денег. Вот и беситесь с жиру, выкидываете бабки на всякие утилиты, и без которых ясно, что к чему... С другой стороны, всяким кувертюрам тоже жить надо - у них свои семьи, дети.
...
Рейтинг: 0 / 0
Универсальный setter
    #38532137
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320всяким кувертюрам тоже жить надо - у них свои семьи, дети.
Вопрос только в том, когда падет Рим.
:-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38535598
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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); }
    }
}


Ну вот и первый камушек...

Значит, в MVVM, если мы используем модель как поле, хранящее значение свойств модели представления (т. е. в самой модели представления отдельных полей для хранения значений свойств нет), то так, как я выше написал в сеттере, сделать нельзя.

Т. е. если имеем

Код: c#
1.
2.
3.
4.
class Model
{
    public int A { get; set; }
}



То вот так сделать нельзя

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
class ViewModel
{
    Model _model;
    
    public int A
    {
        get { return _model.A; }
        set { SetProperty(ref _model.A, value); }
    }
}



Т. к. получим исключение "A property, indexer or dynamic member access may not be passed as an out or ref parameter".

А получится сделать вот так

Код: c#
1.
2.
3.
4.
5.
6.
        set
        {
            var a = _model.A;
            SetProperty(ref a, value);
            _model.A = a;
        }



Кто-нибудь может подсказать, как обойти это? Или как реализацию SetProperty поменять, чтобы и для таких случаев срабатывало?
...
Рейтинг: 0 / 0
Универсальный setter
    #38535632
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
public int A
{
    set { SetProperty(v => _model.A = v, value); }
}
...
Рейтинг: 0 / 0
Универсальный setter
    #38535642
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320
Кто-нибудь может подсказать, как обойти это? Или как реализацию SetProperty поменять, чтобы и для таких случаев срабатывало?

Код: c#
1.
2.
3.
4.
5.
6.
7.
SetProperty (string proprtyName)
{
    if (OnPropertyCanged != null)
    {
         OnPropertyCanged (new ProprtyChangedEvenArgument(proprtyName));
    }
}



:-))))))))))))
...
Рейтинг: 0 / 0
Универсальный setter
    #38535645
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129user7320Кто-нибудь может подсказать, как обойти это? Или как реализацию SetProperty поменять, чтобы и для таких случаев срабатывало?

Код: c#
1.
2.
3.
4.
5.
6.
7.
SetProperty (string proprtyName)
{
    if (OnPropertyCanged != null)
    {
         OnPropertyCanged (new ProprtyChangedEvenArgument(proprtyName));
    }
}



:-))))))))))))Нет! В этом случае с программой разберётся любой посторонний. Нам это не надо! :-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38535791
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129user7320Кто-нибудь может подсказать, как обойти это? Или как реализацию SetProperty поменять, чтобы и для таких случаев срабатывало?

Код: c#
1.
2.
3.
4.
5.
6.
7.
SetProperty (string proprtyName)
{
    if (OnPropertyCanged != null)
    {
         OnPropertyCanged (new ProprtyChangedEvenArgument(proprtyName));
    }
}



:-))))))))))))
А где тут присвоение значения?

Алексей К
Код: c#
1.
2.
3.
4.
public int A
{
    set { SetProperty(v => _model.A = v, value); }
}


А выполнение? Что-то типа такого?

Код: c#
1.
2.
3.
4.
5.
protected void SetProperty<T>(Expression<Action<T>> e, T value, [CallerMemberName] string propertyName = "")
{
    var action = e.Compile();
    action.Invoke(value);
}



А как такую проверку сделать?

Код: c#
1.
2.
3.
4.
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
            }



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

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
protected void SetProperty<T>(Func<T> getter, Action<T> setter, T newValue, [CallerMemberName] string propertyName = "")
{
    var oldValue = getter();

    if (!EqualityComparer<T>.Default.Equals(oldValue, newValue))
    {
        setter(newValue);
        OnPropertyChanged(propertyName);
    }
}
...
Рейтинг: 0 / 0
Универсальный setter
    #38535812
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320и делать сравнение в SetProperty - если не равны, то выполнять делегат, а если равны, то не выполнять?

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
 public ReceiptLine SelectedReceiptLine
        {
            get { return _selectedGiftReceiptLine; }
            set
            {
                if (_selectedReceiptLine == value) return;
                _selectedReceiptLine = value;
                NotifyPropertyChanged("SelectedReceiptLine");
            }
        }



И вот реализация (!!!) NotifyPropertyChanged:

Код: c#
1.
2.
3.
4.
5.
6.
7.
 protected void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }



Транспортное средство двухколесное изобретать будем?
:-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38535825
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Напиши уже T4 Template какой-нибудь или кодогенератор для XML. Там работы на 20 минут.
...
Рейтинг: 0 / 0
Универсальный setter
    #38535839
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или вообще вот так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
class MyEntity
{
    public virtual int Value { get; set; }
}

// Там внутри через Emit замутить потомка указанного класса, перекрыть виртуальное
// свойство и сгенерировать в него что хочешь.
var obj = NotificationFactory.Create<MyEntity>();


Тут пример реализации.
...
Рейтинг: 0 / 0
Универсальный setter
    #38535845
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если надо работать с инкапсулированной моделью оно будет выглядеть так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
class MyViewModel
{
   public virtual int Value 
   { 
       get { return _model; } 
       set { _model.Value = value; }
   }
}
...
Рейтинг: 0 / 0
Универсальный setter
    #38535850
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129user7320и делать сравнение в SetProperty - если не равны, то выполнять делегат, а если равны, то не выполнять?

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
 public ReceiptLine SelectedReceiptLine
        {
            get { return _selectedGiftReceiptLine; }
            set
            {
                if (_selectedReceiptLine == value) return;
                _selectedReceiptLine = value;
                NotifyPropertyChanged("SelectedReceiptLine");
            }
        }



И вот реализация (!!!) NotifyPropertyChanged:

Код: c#
1.
2.
3.
4.
5.
6.
7.
 protected void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }



Транспортное средство двухколесное изобретать будем?
:-)
У вас всё стандартно. А у меня - инкапсулировано в базовом классе. Мне надо только унаследоваться от этого базового класса и в нужном виде (см. мой ответ Алексею ниже) писать сеттер.

Кстати, NotifyPropertyChanged - лучше через временную переменную :

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
 protected void NotifyPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }




Алексей Кuser7320У тебя от экспешенов уже крыша поехала. :-)

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
protected void SetProperty<T>(Func<T> getter, Action<T> setter, T newValue, [CallerMemberName] string propertyName = "")
{
    var oldValue = getter();

    if (!EqualityComparer<T>.Default.Equals(oldValue, newValue))
    {
        setter(newValue);
        OnPropertyChanged(propertyName);
    }
}


Спасибо. Сеттер, конечно, чего-то разросся:

Код: c#
1.
set { SetProperty(() => _model.A, newValue => _model.A = newValue, value); }



Надеюсь, больше косяков не всплывёт, а то, если ещё придётся сеттер усложнять, то придётся, наверное, бросить эту затею с универсальным сеттером.
...
Рейтинг: 0 / 0
Универсальный setter
    #38535854
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КИли вообще вот так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
class MyEntity
{
    public virtual int Value { get; set; }
}

// Там внутри через Emit замутить потомка указанного класса, перекрыть виртуальное
// свойство и сгенерировать в него что хочешь.
var obj = NotificationFactory.Create<MyEntity>();


Тут пример реализации.
Пока что моё своёство с двумя лямбдами выглядит приятнее. ))
...
Рейтинг: 0 / 0
Универсальный setter
    #38535874
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320А зачем тебе проверка на равенство старого и нового значения? Если для красоты, то оно того не стоит. :-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38535999
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кuser7320А зачем тебе проверка на равенство старого и нового значения? Если для красоты, то оно того не стоит. :-)
Стоит.

1. При равенстве я не вызываю PropertyChanged.

2. Соответственно 1, не срабатывают байндинги.

3. Не вызывается цепочка сеттеров в случае, что я описал выше - т. е. когда модель представления не хранит свои копии значений свойств модели, а "пробрасывает" их в модель. И это в простом случае, когда у меня только VM и M, а если таких пробрасывателей больше?

Ну и апелляция к авторитетам .
...
Рейтинг: 0 / 0
Универсальный setter
    #38536005
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Ну и апелляция к авторитетам .
Наконец то!
:-)))))
...
Рейтинг: 0 / 0
Универсальный setter
    #38536016
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
D129user7320Ну и апелляция к авторитетам .
Наконец то!
:-)))))
А вы, я так понимаю, против всяких универсальных сеттеров и максимум за что за - чтобы то стандратное, что вы выше приводили, генерилось сниппетами или шаблонами? Ну и потом в region'ы всё это непотребство спрятать, чтобы глаза не мозолило?
...
Рейтинг: 0 / 0
Универсальный setter
    #38536219
Белый ворон
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще можно Castle.DynamicProxy использовать.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536258
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Стоит.Нет. Это "экономия на спичках" за редкими исключениями.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536341
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кuser7320Стоит.Нет. Это "экономия на спичках" за редкими исключениями.
Цепочки сеттеров, байндинги и лишние события - причём почти всегда это всё одновременно - "экономия на спичках"? При том, что нам сделать такую проверку ничего не стоит - вынес в базовый класс и написал один раз две строчки кода.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536343
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кuser7320Стоит.Нет. Это "экономия на спичках" за редкими исключениями.
Приведите пример исключения, пожалуйста.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536350
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320При том, что нам сделать такую проверку ничего не стоит - вынес в базовый класс и написал один раз две строчки кода.Ну тебе виднее. :-)
user7320Алексей КНет. Это "экономия на спичках" за редкими исключениями.
Приведите пример исключения, пожалуйста.Ну может, как ты и говорил, производительность. Хотя, в сеттерах медленного кода по идее быть не должно. Пока всё. Если ещё что придумаю - отпишу. :-)

зы: Не стоит забывать, что в DependencyProperty, к которому выполняется привязка, есть встроенная проверка на равенство старого и нового значения. Делай выводы.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536364
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Кuser7320При том, что нам сделать такую проверку ничего не стоит - вынес в базовый класс и написал один раз две строчки кода.Ну тебе виднее. :-)
user7320пропущено...

Приведите пример исключения, пожалуйста.Ну может, как ты и говорил, производительность. Хотя, в сеттерах медленного кода по идее быть не должно. Пока всё. Если ещё что придумаю - отпишу. :-)

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

Ну а если по коллекции проходишься и делаешь изменения - тогда уже не "экономия на спичках"?
...
Рейтинг: 0 / 0
Универсальный setter
    #38536605
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Ну а если по коллекции проходишься и делаешь изменения - тогда уже не "экономия на спичках"?Ну сколько там записей? Тысяча, не больше поди...
...
Рейтинг: 0 / 0
Универсальный setter
    #38536612
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И вообще, это попахивает преждевременной оптимизацией.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536644
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей КИ вообще, это попахивает преждевременной оптимизацией.
А без проверок - недостаточная длина кода.
...
Рейтинг: 0 / 0
Универсальный setter
    #38536673
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320Алексей КИ вообще, это попахивает преждевременной оптимизацией.
А без проверок - недостаточная длина кода.Это да. :-)
...
Рейтинг: 0 / 0
Универсальный setter
    #38538167
Фотография D129
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
user7320D129пропущено...

Наконец то!
:-)))))
А вы, я так понимаю, против всяких универсальных сеттеров и максимум за что за - чтобы то стандратное, что вы выше приводили, генерилось сниппетами или шаблонами? Ну и потом в region'ы всё это непотребство спрятать, чтобы глаза не мозолило?
Я не поленюсь и написать, печатаю я быстро, да и не особо нужно сейчас печатать - с автоподсказками-то...

Регионы - зло. Все в коде, что не код - должно быть стерто.
Мне приходилось работать с файлами кода по 12 тысяч строк.
Каждый раз, когда я в том файле встречал регион - я стирал его со словами - ты, гад, еще и скрыть от меня что-то хочешь?
:-)
...
Рейтинг: 0 / 0
65 сообщений из 65, показаны все 3 страниц
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Универсальный setter
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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