Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
RaevskiAnatoly
33 / 34 / 12
Регистрация: 04.03.2017
Сообщений: 424
1

Какое зло из двух меньшее?

28.03.2018, 19:21. Просмотров 990. Ответов 6

Меня всегда раздражал практически идентичный код в некоторых местах кода. Но порой проще смирится с этим, ведь решение обойдется дороже , возможно, в плане производительности, и количестве работы. Такая вот дрянь и в паттерне MVVM. Если есть любая не OneTime или OneWayToSource привязка, то должен быть реализован интерфейс INotify... даже и писать полное имя не хочется. В каждом прибиндиваемом свойстве обязательно будет однотипный код, вроде проверки не было ли это значение, что и до, обязательный вызов события с поверкой на null, в лучше случае для этой однотипной работы будет создан абстрактный класс с объявленными событиями и методом OnPropertyChanged.
Решить эту проблему трудно. Можно сделать с помощью рефлексии, но медленно, да и прописывать все время в придачу к свойству nameof тоже утомляет. Можно последовать способу обертывания, что я и решил попробовать сделать.
Обертка :
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 abstract class TypeShell : PropertyChangedNotifer, INotifyPropertyChanging
    {
        public event PropertyChangingEventHandler PropertyChanging;
        protected object IncapsulatePropertyValue;
 
        protected TypeShell(object incapsulatePropertyValue) => IncapsulatePropertyValue = incapsulatePropertyValue;
 
        protected void OnPropertyChanging(string propertyName)
            => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
    }
 
    public class TypeShell<T> : TypeShell
    {
        public T Value
        {
            get => (T) IncapsulatePropertyValue;
            set
            {
                if (Equals(value, IncapsulatePropertyValue))
                    return;
                OnPropertyChanging(nameof(Value));
                IncapsulatePropertyValue =  value;
                OnPropertyChanged(nameof(Value));
            }
        }
 
        private TypeShell(T value) : base(value)
        {
            
        }
 
 
        public static implicit operator TypeShell<T>(T value) => new TypeShell<T>(value);
        public static implicit operator T(TypeShell<T> value) => (T) value.IncapsulatePropertyValue;
    }
Допустим, примитивная viewmodel:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
    public class SmartViewModel
    {
        public TypeShell<string> Name { get; } = "My name is fiddooor";
 
        public SmartViewModel()
        {
            Task.Factory.StartNew(() =>
            {
                Thread.Sleep(3000);
                Name.Value = "!";
            });
        }
    }
Но все равно нужно будет все время писать Property.Value!!! Хоть застрелись опять повторяющийся код.
Можно еще написать расширение разметки, чтобы в xaml не писать все время.Value
Вот и как это разрешить, и что лучше
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.03.2018, 19:21
Ответы с готовыми решениями:

Вывести сначала большее, а затем меньшее из двух чисел
Даны два числа. Вывести сначала большее, а затем меньшее из них.

Меньшее из двух чисел заменить половиной их суммы, а большее — их удвоенным произведением
2.30. Даны действительные числа x и y, не равные друг другу. Меньшее из этих двух чисел заменить...

Меньшее из двух чисел заменить половиной их суммы, а большее - их удвоенным произведением
Даны действительные числа x и y, не равные друг другу. Меньшее из этих двух чисел заме-нить...

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

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

6
Wlk
90 / 90 / 48
Регистрация: 07.12.2011
Сообщений: 215
Завершенные тесты: 4
28.03.2018, 19:43 2
Цитата Сообщение от RaevskiAnatoly Посмотреть сообщение
нужно будет все время писать Property.Value!!!
Ну это как бы ок.

Но если прям не в моготу, то можно попробовать что-то типа:

C#
1
2
3
4
5
6
7
8
private TypeShell<string> _name { get; } = "My name is fiddooor";
 
public string Name { 
  get 
  {
     return _name.Value;
  }
}
1
Usaga
Эксперт .NET
5785 / 4031 / 718
Регистрация: 21.01.2016
Сообщений: 15,792
Завершенные тесты: 2
29.03.2018, 05:48 3
Лучший ответ Сообщение было отмечено RaevskiAnatoly как решение

Решение

RaevskiAnatoly, так как вы никто не делает. Обычно наследуют всю View Model от астрактного класса, а не отдельные свойства заворачивают.

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public abstract class NotifyPropertyChangedViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected virtual void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
 
        protected void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                NotifyPropertyChanged(propertyName);
            }
        }
    }


А потом просто вызывают метод базового класса:
C#
1
2
3
4
5
6
7
8
9
    public class SmartViewModel : NotifyPropertyChangedViewModel
    {
        private string _name;
        public string Name  
        {
             get { return _name; }
             set { SetField(ref _name, value) }
        }
    }
Дешёво и сердито.

Есть другой вариант: использовать библиотечку PropertyChanged.Fody, которая пропатчит ваше приложение сразу после сборки и сама вставит аналог SetField в каждый сеттер.
2
RaevskiAnatoly
33 / 34 / 12
Регистрация: 04.03.2017
Сообщений: 424
29.03.2018, 11:53  [ТС] 4
Цитата Сообщение от Usaga Посмотреть сообщение
SetField(ref _name, value)
А почему не передается имя свойства?
0
Usaga
Эксперт .NET
5785 / 4031 / 718
Регистрация: 21.01.2016
Сообщений: 15,792
Завершенные тесты: 2
29.03.2018, 11:54 5
RaevskiAnatoly, потому, что оно определяется самим компилятором:

C#
1
protected void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
1
RaevskiAnatoly
29.03.2018, 12:02  [ТС]
  #6

Не по теме:

А еще думал, что все-таки дают эти атрибуты, что мне студия втирает)

0
jr_
133 / 134 / 52
Регистрация: 14.06.2016
Сообщений: 466
Завершенные тесты: 5
29.03.2018, 15:23 7
еще дешевле - снипеты зачем по вашему придумали ?
XML
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
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
        <Header> 
            <Title>Property With Change Event</Title> 
            <Shortcut>propn</Shortcut> 
            <Description>Code snippet for property that calls RaisePropertyChanged and XML description</Description> 
            <Author>PLaker</Author> 
            <SnippetTypes> 
                <SnippetType>Expansion</SnippetType> 
            </SnippetTypes> 
        </Header> 
        <Snippet> 
            <Declarations> 
                <Literal> 
                    <ID>type</ID> 
                    <ToolTip>Property type</ToolTip> 
                    <Default>string</Default> 
                </Literal> 
                <Literal> 
                    <ID>property</ID> 
                    <ToolTip>Property name</ToolTip> 
                    <Default>MyProperty</Default> 
                </Literal> 
            </Declarations> 
            <Code Language="csharp">
          <![CDATA[#region $type$ $property$
          private $type$ _$property$; 
            public $type$ $property$ { 
                get 
        { 
            return _$property$; 
        } 
                set 
        { 
            if (_$property$ != value)
            {
                _$property$ = value; 
                NotifyPropertyChanged(nameof($property$)); 
            }
        }
            } 
            #endregion$end$]]></Code> 
        </Snippet> 
    </CodeSnippet> 
</CodeSnippets>
0
Миниатюры
Какое зло из двух меньшее?  
29.03.2018, 15:23
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.03.2018, 15:23

Найти меньшее из двух значений
В С++ шарю поверхностно. Недавно разобралась только с простенькими массивами, а тут уже задали...

Вывести меньшее из двух целых чисел
Даны два целых числа. Вывести меньшее из них.

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru