Pull to refresh
97
0
Send message
Да, конечно интересно )
Хорошая идея, спасибо! Но сама врезка получится менее тривиальной. Скорее всего нужно будет копировать тело функции под другим именем (фактически переименовать исходную функцию), а вместо тела исходной добавить тело адвайса. Возможно мы добавим такую фичу, например в виде типа точки врезки InjectionPoints.Around.
Это не придирка, а констатация проблем, неоднократно случавшихся на практике.
Я, к сожалению, помню проблемы из практики на реально большом проекте, когда после переименования возникали подобные проблемы.
Спасибо за понимание! :)
Во-первых, что такое «другой поток» в контексте INotifyPropertyChanged?

Согласен, что не совсем корректно выразился. Расшифрую. Чаще всего мы работаем не со «сферическим конем в вакууме», а с конкретной ситуацией, когда INotifyPropertyChanged используется UI фреймворком для получения информации об изменениях свойств. UI работает в «главном» потоке приложения, его же называют «UI поток». И вызов обработчиков события PropertyChanged из любого другого потока в данной ситуации не есть правильным.

Во-вторых, вы этим предложением на все свойства объекта и члены INotifyPropertyChanged наложили невидимый контракт, запрещающий их вызов из определённых потоков, а также заставляющий PropertyChanged тоже вызываться в каком-то «не другом» потоке. Это нарушение сразу многих принципов объектно-ориентированного программирования. Короче говоря, так делать нельзя.

Допустим, у меня есть вьюмодел с множеством свойств, пара из которых может устанавливаться как из UI, так и из фонового потока. Причем установка из UI потока делается намного чаще, чем из фонового. Что делать?

В-третьих, это искусственное ограничение вашего фреймворка, который почему-то берёт на себя проблемы самого объекта (или инфраструктуры проекта-пользователя). Вот, например, мой концепт вызова PropertyChanged в разных потоках.

Насчет искусственного ограничения вообще не понял — не вижу проблем написать аспект, который будет диспатчить вызовы. Приведенные выше примеры аспектов — они не встроены во фреймворк, они могут быть написаны и заинжекчены с помощью него, со всеми нюансами, которые вам нужны. И тут еще на всякий случай замечу, что синхронизация доступа бесплатно не дается, поэтому объявление всех свойств модели как «принудительно синхронизированных» может не очень хорошо сказаться на производительности.
Только потом, при переименовании свойства, RaisePropertyChanged с большой вероятностью будет нотифицировать по старому имени (если сам разработчик или какой-нибудь решарпер не заметит)
до огромных проблем при многопоточном использовании


Каким образом проблемы многопоточного использования решает ваш сниппет? Из других потоков звать нотификацию нельзя, и об этом нужно явно заботиться, т.е. не изменять свойства вьюмодела напрямую из другого потока.
Автоматизация INPC — всего лишь один из примеров использования. Повторюсь, что Aspect Injector — универсальный фреймворк, а не «еще один NotifyPropertyWeaver».
Добавил в статью пример сгенерированного кода. Как можно увидеть из примера, падение производительности будет зависеть в первую очередь от сложности конструкторов аспектов и количества аспектов на одном классе, так как создание их экземпляров «врезается» в конструктор «цели». Я подумаю над тем, как лучше выразить падение производительности.
NotifyPropertyWeaver — узкоспециализированный инструмент, который предназначен для решения одной задачи. Aspect Injector — инструмент для создания и инжекции любых аспектов, не только для реализации INotifyPropertyChanged. И в отличие от Fody в нем не нужно писать или подключать плагины — достаточно у себя в коде объявить класс аспекта и затем привязывать его к любым «целям». Никаких дополнительных действий кроме подключения Aspect Injector не нужно. Плюс ко всему — отладка без проблем заходит в методы созданных аспектов. Пример сгенерированного кода можно увидеть в статье (недавно добавил).
12 ...
7

Information

Rating
Does not participate
Registered
Activity