Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.55/29: Рейтинг темы: голосов - 29, средняя оценка - 4.55
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
.NET 4.x

Как получить свойство класса?

13.06.2017, 22:23. Показов 7160. Ответов 101
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В продолжении темы визитора Есть, к примеру, вот такой код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface IAnimals 
{
   string Name { get; set; } 
}
 
public class Dog : IAnimals
{
    public string Name { get; set; }
    public bool Ears { get; set; } = true;
}
 
public class Cat : IAnimals
{
    public string Name { get; set; }
    public bool Tail { get; set; } = false;
}
public class Squirel: IAnimals
{
    public string Name { get; set; }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var secondAnimal = new List<IAnimals>(){new Cat(), new Dog(), new Squirel()};
 
bool haveTail;
foreach (IAnimals currentAnimal in secondAnimal)
{
    if (currentAnimal is Cat)
    {
      haveTail = (currentAnimal as Cat).Tail;
      break;
    }
    if (currentAnimal is Dog)
    {
      (currentAnimal as Dog).Ears = true;
    }
}
Как нужно реализовать код, чтобы не использовать приведение типов при получении и установке значения свойства?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.06.2017, 22:23
Ответы с готовыми решениями:

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

Как поместить свойство класса типа Enum в конструктор
Привет, создал интерфейс: interface IPerson { string Firstname { get; } string Lastname { get; } ...

Можно ли как-то получить из одного класса исходный код другого класса?
Предположим есть два публичных класса. Один находится в одной части проекта, другой где-нибудь в другой части проекта. Мне для своих...

101
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
16.06.2017, 08:30
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Usaga Посмотреть сообщение
Я настаивал на том, что нужно в визитёр выносить не чтение\установку свойства, а всю логику, в которой данное действие происходит.
В это был и другой смысл: если вам нужно только прочитать свойство или его установить, то визитёр тут будет просто избыточен:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        public class SomeEntityPropertySetter : ISomeVisitor
        {
            private string propValue;
            public SomeEntityPropertySetter(string propValue)
            {
                this.propValue = propValue;
            }
 
            public void VisitDog(Dog dog)
            {
                dog.SomeProperty = propValue;
            }
        }
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
16.06.2017, 08:43  [ТС]
Возможно тут я использовал слово не в том контексте. Сорян.

Добавлено через 43 секунды
Цитата Сообщение от Usaga Посмотреть сообщение
то визитёр тут будет просто избыточен
Но его же посоветовали чтоб уйти от каста

Добавлено через 3 минуты
Usaga, я понимаю, что читать чужой код часто бывает трудно. Особенно если он написан не профессионалом.
Но в той теме прям вот кусок ViewModel выложен Классы или интерфейсы?
вы его пропустили. Отсюда и ваши вопросы и недопонимание. + моя местами программерская безграмотность. Но мы же вроде в теме "новичков" )))

Добавлено через 7 минут
Ну а теперь представьте:
то свойство Item (в том коде) это:
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
36
37
38
39
40
public interface ISpecificationItem 
{
 string Designation {get;set;}
 string Name {get;set;}
 //ещё штук 15
...
 SetDeep();
 SetNotReal();
...
}
 
public class Part : ISpecificationItem 
{
 public string Designation {get;set;}
 public string Name {get;set;}
// ещё штук 15 свойств
 
...
// уникальные
    public SignPeople SignPeople {get;set;}
...
}
 
public class SignPeople 
{
   public string Designer {get;set;}
   public string Manager {get;set;}
}
 
public class Material: ISpecificationItem 
{
 public string Designation {get;set;}
 public string Name {get;set;}
// ещё штук 15 свойств. SignPeople - в этом классе нет и быть не может.
 
...
// уникальные 
public double Thickness{get;set;}
...
}
Добавлено через 2 минуты
Цитата Сообщение от Usaga Посмотреть сообщение
private string propValue;
public SomeEntityPropertySetter(string propValue)
{
this.propValue = propValue;
}
Именно это и написал Storm23. А у вас возникли вопросы по этому. И тут ВЫ уже это пишете )))
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
16.06.2017, 08:59
Цитата Сообщение от skilllab Посмотреть сообщение
Но его же посоветовали чтоб уйти от каста
Да, верно. Я предполагал, что у вас гораздо больше логики в коде.

Цитата Сообщение от skilllab Посмотреть сообщение
Именно это и написал Storm23. А у вас возникли вопросы по этому. И тут ВЫ уже это пишете )))
Этот видитёр узкоспециализированный, он умеет только у конкретного класса выставлять только конкретное свойство. Целый класс ради этого действа Делать универсально - значит возвращаться к тому, с чего начали.

По поводу фрагмента кода.

Содержимое описанное интерфейсом ISpecificationItem можно было бы вынести в отдельный класс, который либо будет контейнером для всех остальных, либо же сам будет включаться во все остальные классы. Получается, что это и есть точка соприкосновения классов. И нужно оно, как я понял, только для отображения в DataGrid. Тут получается, что способ визуализации у вас пролез в модель данных и бизнес-логику, что не есть гуд.

Добавлено через 3 минуты
И ещё: интерфейсом выражают действия, которые можно совершить над классом, а не его содержимое (IClonnable, IComaprable).
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
16.06.2017, 09:10  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Этот видитёр узкоспециализированный, он умеет только у конкретного класса
Или так, или в визитёре лепить ВСЕ уникальные свойства со ВСЕХ моих классов. Угу
ISpecificationItem - это базовая сущность. SpecRowViewModel - это модель представления для сущностей.
Цитата Сообщение от Usaga Посмотреть сообщение
Тут получается, что способ визуализации у вас пролез в модель данных
Эммм...DataGrid ничего не знает об ISpecificationItem.

Добавлено через 3 минуты
Цитата Сообщение от Usaga Посмотреть сообщение
интерфейсом выражают действия, которые можно совершить над классом
Цитата Сообщение от skilllab Посмотреть сообщение
SetDeep();
SetNotReal();
там есть ещё что совершать НАД классом. В свою очередь, в классе расписано ЧТО нужно совершать в конкретно этом классе. Ибо SetDeep() для Part это одно, а SetDeep() для Material - вообще другое. Т.е. метод SetDeep() работает с внутренними, присущими только конкретному классу, свойствами. А результат должен быть один => у каждого класса есть свойство double DeepCount {get;set;}

Добавлено через 5 минут
Цитата Сообщение от Usaga Посмотреть сообщение
способ визуализации у вас пролез в модель данных
Не совсем понял поняли ли вы меня правильно)))
Для ячейки в строке DataGrid (в столбце "обозначение материала"), класс SpecRowViewModel берёт свойство класса Material как Materia:Designation, а для класса Part берёт как Part:MaterialPanelData:MaterialDesignation Кто тут куда просачивается по вашему - я не понял.

Добавлено через 1 минуту
Цитата Сообщение от Usaga Посмотреть сообщение
можно было бы вынести в отдельный класс, который либо будет контейнером для всех остальных, либо же сам будет включаться во все остальные классы.
Об чём и писал Storm23 и я у него попросил чуть больше разъяснений. Может реально нужно что-то сделать по другому.
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
16.06.2017, 09:10
Цитата Сообщение от skilllab Посмотреть сообщение
ISpecificationItem - это базовая сущность
Тогда сделайте его классом (возможно абстрактным) и переименуйте.

Цитата Сообщение от skilllab Посмотреть сообщение
SpecRowViewModel - это модель представления для сущностей.
Значит это и есть обёртка над объектом для его отображаения в DataGrid?
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
16.06.2017, 09:13  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Значит это и есть обёртка
Да. ...ViewModel на это какбэ намекает)))
Цитата Сообщение от Usaga Посмотреть сообщение
Тогда сделайте его классом (возможно абстрактным) и переименуйте.
Можно и так. Внутреннее содержание каждого класса, которые у меня сейчас имплементируют интерфейс ISpecificationItem) (это я про свойства, методы) от этого НЕ изменится.
Цитата Сообщение от Usaga Посмотреть сообщение
Тут получается, что способ визуализации у вас
Не надо только предлагать конвертеры XAML-a или TemplateSelector))) Сейчас там итак всё есть и всё работает. Речь в теме именно о модели данных.
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
16.06.2017, 09:17
skilllab, видите в чём проблема. Чтобы дать точный и конкретный совет или рекомендацию, нам нужно обладать всей информацией: что есть, почему оно так сделано было, а не иначе, какие взаимосвязи между объектами.

Предоставленной информации уже хватило, чтобы понять, что пути решения есть.

Добавлено через 1 минуту
Цитата Сообщение от skilllab Посмотреть сообщение
Не надо только предлагать конвертеры XAML-a или TemplateSelector)))
И не собирался.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
16.06.2017, 09:24  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
нам нужно обладать всей информацией
Ну так вот: в коде пробегаясь по коллекции этих SpecRowViewModel (это абстрактный класс) ищу кто там именно SpecMaterialRow:SpecRowViewModel и дёргаю у него именно то самое уникальное свойство Thickness, которого НЕТ в абстрактном классе. Вот тут-то и возникает каст )))


Добавлено через 15 секунд
Цитата Сообщение от Usaga Посмотреть сообщение
нам нужно обладать всей информацией
Ну так вот: в коде пробегаясь по коллекции этих SpecRowViewModel (это абстрактный класс) ищу кто там именно SpecMaterialRow:SpecRowViewModel и дёргаю у него именно то самое уникальное свойство Thickness, которого НЕТ в абстрактном классе. Вот тут-то и возникает каст ))) Который вот уже на протяжении 2-х тем обсасываю как применить визитёра, вместо каста.
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
16.06.2017, 09:56
Лучший ответ Сообщение было отмечено skilllab как решение

Решение

skilllab, я могу вам предложить одно решение. Без кастов и визитёров. Я не уверен, что оно не попахивает наркоманией, но всё же.

Вы раскладываете свои объекты строго по разным коллекциям, в соответствии с их типами. Коллекции типизированы конкретными типами, а не общим классом. Формируете "основную" коллекцию, которая для DataGrid (или ещё для чего). В неё набиваете все объекты из всех других коллекций предварительно завернув их в свою обёртку SpecRowViewModel. В эту обёртку добавляете целочисленный или строковой признак типа объекта и ссылку (типа object или базового класса) на данный объект. При переборе, вы определяете (по признаку) в какой коллеции искать объект, потом лезете в нужную коллецию и там его ищите по ссылке из SpecRowViewModel. Профит.

Или такой вариант: опять же, в обёртке есть признак типа объекта и пять свойств для каждого возможного "завёрнутого" типа. Валидено, естественно, будет только одно. Опять же, никакого кастинга. Посмотрели, что в признаке, обратились к нужному свойству. Или даже без признака, просто свойства перебираем, пока попадётся то, что не null.

Как вам такие варианты? Никаких визитёров, никаких кастов и рефлексии. В модели данных вмешиваться не нужно, так как всё возня будет только в обёртке, на которую вообще плевать.

А?

Добавлено через 2 минуты
Второй вариант выглядит вполне себе рабочим. И быстрым. Посмотрели на признак - обратились к нужному свойству. Тут даже перебирать ничего ненужно (я про отдельные коллекции для каждого типа объектов). Простой switch где надо и всё.

Добавлено через 1 минуту

Не по теме:

Блин, что я раньше-то не подумал так вам посоветовать. Мозг засрал визитёрами всякими в двух темах. :D



Добавлено через 16 минут
Кстати, у вас как SpecRowViewModel определяет куда нужно лезть за данными? У вас пять вариантов SpecRowViewModel или через те же IS\AS?
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
16.06.2017, 10:18  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
У вас пять вариантов SpecRowViewModel
да Т.е. под каждую сущность свой ...ViewModel но, от одного абстрактного класса SpecRowViewModel. Тип ...ViewModel теперь уже определяю по некоему EViewModel Tag {EViewModel.Part; EViewModel.Material...} и далее уже конкретный каст.
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
16.06.2017, 10:27
skilllab, не нужно кастить. Пять ссылок на пять разных типов. Только одна будет указывать на нужное и будет задаваться при создании объекта-обёртки. Не могу сказать, что это элегантное решение, но для вашего случая вполне проканает.

Я бы постарался сделать иначе, более правильно. Но, думаю, что уже хватит тему мусолить.
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
16.06.2017, 10:32  [ТС]
" сделать иначе, более правильно" - тогда уже, с учётом узнанного вами от меня, про модель данных, вам уже нужно будет зарплату платить
Там уже работа пойдёт, а не помощь на форуме.
Я опробую ваше предложение выше на выходных. Спасибо.
Будет затык. В эту же тему напишу.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10428 / 5158 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
16.06.2017, 11:54
Цитата Сообщение от skilllab Посмотреть сообщение
Ну или на примерчик какой показательный.
Я почитал эту ссылку Классы или интерфейсы? откуда я примерно понял чего вы хотите. Хотя я просил обрисовать вашу задачу, но вы так внятно и не объяснили.
Поэтому я сам себе придумаю проблему и сам же ее попытаюсь решить
Итак, у нас есть входной список god-объектов (на самом деле плоская таблица). Каждая строка содержит некий enum, который определяет тип строки. При этом строка может содержать разные свойства, которые мы хотим отобразить в гриде. Проблема в том, что свойство Name может быть в разных свойствах исходного объекта, в зависимости от его "типа".

Наша исходная задача в виде кода выглядит так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    //исходные данные в виде God объекта
    class GodObject
    {
        public RowType RowType { get;set;}
 
        //Свойство Name может быть в PartName а может быть и в MaterialNameInBase, в зависимости от RowType
        public string PartName { get; set; }
        public string MaterialNameInBase { get;set;}
    }
 
    //"тип" god объекта
    enum RowType
    {
        Part,//деталь
        Material,//материал
        Empty//разделитель (OMG, что он здесь делает?)
    }
 
    //View модель которую нам нужно реализовать
    interface IRowViewModel
    {
        string Name { get; set; }
    }
Наша задача сделать реализацию IRowViewModel так, что бы свойство Name обращалось с разными свойствами исходного объекта, в зависимости от "типа".

Я так понимаю вы пытаетесь решать эту проблему следующим образом:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    #region вариант 0 (stupid)
 
    class RowViewModel : IRowViewModel
    {
        object source { get;set;}
 
        string Name
        {
            get
            {
                if (source is Part) return (source as Part).PartName;
                if (source is Material) return (source as Material).MaterialNameInBase;
                //...
            }
        }
    }
 
    #endregion
Это решение "в лоб". Такой вариант плох тем, что добавление нового класса требует перекапывания всей модели и добавления новых as/is в каждом свойстве модели. А нам бы хотелось бы что бы view модель была неизменна при добавлении или изменении структуры исходной модели (напоминаю, что я решаю проблему как я ее понимаю, возможно для вас проблема в чем-то другом, я до конца этого не понял).

Альтернативных вариантов решения - масса. Вариант визитора я уже рассматривать не буду, хотя он тоже применим.
Рассмотрим два варианта которые довольно очевидны и приходят на ум сразу:

1) Вариант 1 - специализированные модели (реализуется паттерн стратегия):
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    #region вариант 1 - специализированные модели (паттерн стратегия)
 
    //базовый класс для всех объектов модели
    abstract class BaseItem
    {
        protected GodObject SourceObject { get;set;}
        public abstract IRowViewModel GetModel();
    }
 
    //view модель для объектов
    class ViewModel : IRowViewModel
    {
        public Action<string> NameSetter { get; set; }
        public Func<string> NameGetter { get; set; }
 
        public string Name
        {
            get { return NameGetter(); }
            set { NameSetter(value); }
        }
    }
 
    //объект
    class Part : BaseItem
    {
        public override IRowViewModel GetModel()
        {
            return new ViewModel()
            {
                NameGetter = ()=>SourceObject.PartName,
                NameSetter = (v)=>SourceObject.PartName = v
            };
        }
    }
 
    //объект
    class Material : BaseItem
    {
        public override IRowViewModel GetModel()
        {
            return new ViewModel()
            {
                NameGetter = () => SourceObject.MaterialNameInBase,
                NameSetter = (v) => SourceObject.MaterialNameInBase = v
            };
        }
    }
 
    //объект
    class Empty : BaseItem
    {
        public override IRowViewModel GetModel()
        {
            return new ViewModel()
            {
                NameGetter = () => null,
                NameSetter = (v) => { }
            };
        }
    }
 
    #endregion
Смысл этого подхода в том, что view модель генерирует сам объект. Все объекты унаследованы от BaseItem, который содержит абстрактный метод GetModel. Если мы спросим view модель у объекта типа Part - он вернет модель, настроенную именно для него, объект Material - вернет свою модель и т.д.
Саму модель я сделал через делегаты (это для того, что бы не плодить отдельный класс под каждую модель, хотя возможно это понадобится). Как по мне - это самый естественный путь решения задачи.

2) Второй вариант - компонентная модель. Хотя это не самый очевидный способ решения вашей задачи, она может иметь свои преимущества.
Код:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    #region вариант 2 (компонентная модель, упрощенно)
 
    //компонент
    class Component
    {
    }
 
    //контейнер
    class Container : List<Component>
    {
        public T GetComponent<T>() where T: Component
        {
            return this.OfType<T>().FirstOrDefault();
        }
    }
 
    //компонент Name
    class NameComponent : Component
    {
        public Action<string> NameSetter { get; set; }
        public Func<string> NameGetter { get; set; }
 
        public string Name
        {
            get { return NameGetter(); }
            set { NameSetter(value); }
        }
    }
 
    //парсер god объектов
    class GodObjectsParser
    {
        //возвращает список наших распарсенных "объектов"
        //в компонентной модели классов как таковых нет. каждый объект определяется набором компонент
        public IEnumerable<Container> Parse(IEnumerable<GodObject> rows)
        {
            foreach (var row in rows)
            {
                var res = new Container();
 
                switch (row.RowType)
                {
                    case RowType.Part:
                        res.Add(new NameComponent{ NameGetter = () => row.PartName, NameSetter = (v) => row.PartName = v});
                        //добавляем другие компоненты...
                        break;
 
                    case RowType.Material:
                        res.Add(new NameComponent { NameGetter = () => row.MaterialNameInBase, NameSetter = (v) => row.MaterialNameInBase = v });
                        //добавляем другие компоненты...
                        break;
 
                    case RowType.Empty:
                        //не добавляем компонент, потому что у этого типа компонентов нет
                        break;
                }
 
                yield return res;
            }
        }
    }
 
    //модель ищет нужные компоненты и отображает их
    class ViewModel : IRowViewModel
    {
        Container source { get; set; }
 
        public string Name
        {
            get
            {
                //получаем компонент Name (если он есть)
                return source.GetComponent<NameComponent>()?.Name;
            }
 
            set
            {
                //получаем компонент Name (если он есть)
                var n = source.GetComponent<NameComponent>();
                if(n!= null)n.Name = value;
            }
        }
    }
 
    #endregion
Обратите внимание, в компонентной модели нет классов в привычном понимании. Здесь доменный объект является контейнером компонент и его функционал полностью определяется набором его компонент.
Поэтому здесь нет классов типа Part, Material и т.п. Каждый объект это контейнер с компонентами. Если данный класс поддерживает свойство Name - значит в нем будет компонент NameComponent. Если нет - не такого компонента не будет.
Обращаю внимание на то, что не обязательно делать отдельный компонент на каждое свойство - можно разбить свойства на компоненты содержащие по нескольку свойств, которые всегда идет вместе.

Оба предложенные варианты обеспечивают связь с самым исходным god объектом. но эту связь конечно можно порвать и хранить свойства в оторванном виде, зависит от ваших задач.

Итого, оба предложенные варианты решают исходную задачу:
Изменение внутренней структуры доменных объектов не меняют view model. Моделька отображения остается одинаковой. Если нам нужно добавить новый объект, то логика его отображения задается "по месту" - либо в самом объекте (в первом варианте - в методе GetModel) либо в парсере (во втором варианте).

Вариантов решения на самом деле может быть больше. Например компонентная модель может содержать не компоненты-свойства, а компоненты-аксессоры (accessors) - которые будут не хранить сами свойства а лишь определять способ доступа к свойствам исходного объекта.
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
18.06.2017, 11:28  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
откуда я примерно понял чего вы хотите.
Цитата Сообщение от Storm23 Посмотреть сообщение
Итак, у нас есть входной список god-объектов
и всё.))) НЕТ GOD объектов. А наоборот даже. По вашим примерам "стратегия" - выглядит привлекательно)).

Цитата Сообщение от Usaga Посмотреть сообщение
определяете (по признаку) в какой коллеции искать объект, потом лезете в нужную коллецию и там его ищите по ссылке из SpecRowViewModel. Профит.
Вариант))) Правда потом, может оказаться затык с INotify... что для модели что для VM.

Второй вариант почти та же "стратегия" от Storm23. Просто будет одна толстая SpecRowViewModel с кучей "Метод-Свойство". Хмм...

Добавлено через 16 минут
Цитата Сообщение от Usaga Посмотреть сообщение
Пять ссылок на пять разных типов. Только одна будет указывать на нужное и будет задаваться при создании объекта-обёртки.
Хорошее решение, но как вы сами заметили чуток "попахивает" ))

Добавлено через 1 минуту
Цитата Сообщение от Storm23 Посмотреть сообщение
return this.OfType<T>()
а это не тот же самый кастинг получается?
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
18.06.2017, 13:43
Цитата Сообщение от skilllab Посмотреть сообщение
Просто будет одна толстая SpecRowViewModel
Нет, не будет "толстой" модели. Будет абстрактный класс с пятью ссылками нужных типов и пять специализированных моделей у каждой из которых одна из ссылок указывает на нужный объект. Это было бы совсем хреновое решение, но у вас и так уже есть пять специализированных моделей-обёрток, так ведь?

Цитата Сообщение от skilllab Посмотреть сообщение
Хорошее решение, но как вы сами заметили чуток "попахивает"
Изначальное решение уже "попахивает", так что смена аромата на "la merde №5" хуже не сделает.

Цитата Сообщение от skilllab Посмотреть сообщение
а это не тот же самый кастинг получается
Да, тотже самый кастинг что и через is\as.

Цитата Сообщение от skilllab Посмотреть сообщение
Правда потом, может оказаться затык с INotify... что для модели что для VM.
Не понял, о чём тут.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
18.06.2017, 14:06  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
но у вас и так уже есть пять специализированных моделей-обёрток
Так ваше же решение вроде позволяет уйти от n-количества ViewModel?

Типа как:
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
public class SpecRowViewModel
{
   public SpecRowViewModel(Part _part = null, Material _material = null, Tag _tag = Tag.NONE)
   {
      Part = _part;
      Material = _material;
      Tag = _tag;
   }
   
   public Tag Tag {get;set;}
   public Part Part {get;set;}
   public Material Material {get;set;}
   public string Name
   {
     get
        {
           switch(Tag):
           {
              case Tag.IsPart:
                return Part.MaterialPanelData.MaterialName;
              case Tag.IsMaterial:
                return Material.Name;
              default: throw new NotImplementedException("Добавился тип");
           }
        };
       
     set{.......}};
   }
}
.....
var newVM = new SpecRowViewModel(_part: new Part(name:"Деталюха"), _tag = Tag.Part)
 
string currentName = newVM.Name;
Добавлено через 2 минуты
Цитата Сообщение от Usaga Посмотреть сообщение
Изначальное решение уже "попахивает"
изначальное решение моё с кастом? Или изначальное решение разделять на независимые сущности с некоторым набором только своих свойств + общие для все свойства?

Добавлено через 4 минуты
Хотя даже Tag можно не пихать в конструктор, а инициализировать его. Ну да, чутка метаданных...
Типа как:
C#
1
2
3
4
5
6
7
switch(item?.GetType().Name)
{
   case nameof(Part):
   Tag = Tag.Part;
   break;
.....
}
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
18.06.2017, 14:22
Цитата Сообщение от skilllab Посмотреть сообщение
Так ваше же решение вроде позволяет уйти от n-количества ViewModel?
Вовсе нет. Точнее оно с количеством моделей не связано. Идея проста: несколько аксессеров для доступа к сокрытому объекту. Это может быть как один контейнер на всё (ограниченный в своих познаниях о хранимом объекте), так и несколько специализированных, точно знающих что и как (ваш случай).

Цитата Сообщение от skilllab Посмотреть сообщение
изначальное решение моё с кастом?
Ну да. Даже не так: сама задумка уже была сомнительна, почему я и зацепился и предложил описать задачу подробнее.

Цитата Сообщение от skilllab Посмотреть сообщение
Хотя даже Tag можно не пихать в конструктор, а инициализировать его. Ну да, чутка метаданных...
Ничего не надо искать в метаданных, если у вас есть специализированные View Models точно заточенные на конкретные классы. Пускай они и пишут в Tag в конструкторе, с чем работают.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
18.06.2017, 14:39  [ТС]
Тогда я снова вас не понимаю))
Цитата Сообщение от Usaga Посмотреть сообщение
если у вас есть специализированные View Models точно заточенные на конкретные классы. Пускай они и пишут в Tag в конструкторе, с чем работают.
Чтобы объединить эти специализированные модели в одну коллекцию - их нужно объединить под одним началом (абстрактный класс).
Тогда получается что:


раз:
C#
1
2
3
4
5
6
7
8
9
var currentRowViewModel = SpecRowViewModel; //Это ткнули в DataGrid строку и получили текущую ViewModel.
 
switch(currentRowViewModel.Tag)
{
   case Tag.Part:
   //Как получить значение свойства тут? Без каста к currentRowViewModel = PartViewModel:SpecRowViewModel
   case Tag.Material:
   ....
}
два:
Цитата Сообщение от Usaga Посмотреть сообщение
опять же, в обёртке есть признак типа объекта и пять свойств для каждого возможного "завёрнутого" типа. Валидено, естественно, будет только одно. Опять же, никакого кастинга. Посмотрели, что в признаке, обратились к нужному свойству.
Как обёртка, содержащая object (или абстрактный класс модели), будет брать значение свойства по признаку и при этом не кастуя ссылку на модель? Моделей то не одна штука.
0
Эксперт .NET
 Аватар для Usaga
14811 / 9584 / 1368
Регистрация: 21.01.2016
Сообщений: 36,099
18.06.2017, 15:05
C#
1
2
3
4
5
6
7
8
9
10
11
var currentRowViewModel = SpecRowViewModel; //Это ткнули в DataGrid строку и получили текущую ViewModel.
 
switch(currentRowViewModel.Tag)
{
   case Tag.Part:
       Part part = currentRowViewModel.Detail; // есть и другие свойства: Material, Documentation и т.д., но валидно только это
       part.SomePartSpecificProperty = 42;
       part.DoSomePartMethod();
   case Tag.Material:
       // так же фигня, но валидно свойство Material
}
Цитата Сообщение от skilllab Посмотреть сообщение
Как обёртка, содержащая object (или абстрактный класс модели), будет брать значение свойства по признаку и при этом не кастуя ссылку на модель? Моделей то не одна штука.
Так же, как это будет делать внешний класс. Ну или можно делать по кассу-обёртке на на каждый тип предметной области (деталь, материал, и т.д.).
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
18.06.2017, 15:16  [ТС]
Таак, а в самой ViewModel как будет определяться свойство Detail?
И посмотрев в сообщение 56 - что там не верно? Если вы делаете то же.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.06.2017, 15:16

Свойство класса возвращает объект другого класса
Каким образом можно через свойство получить доступ ко всем методам объекта,который возвращает это свойство?? данный код не работает..можно...

Лямбда выражение в качестве параметра метода. Как получить свойство с которым производится операция?
Добрый день! Нужно в методе принимать лямбду: obj.Get(x=&gt;x.ParentId==5); Как мне из этой лямбды в методе Get получить...

Свойство класса в List(UI)
Доброго времени суток, заинтересовался следующим вопросом. Есть графический компонент List, и пользовательский класс допустим TNumber, у...

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

Как получить ссылку на метод класса
Имеем некоторый класс: using System; using System.Collections.Generic; using System.Reflection; class SomeClass { ...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru