Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/26: Рейтинг темы: голосов - 26, средняя оценка - 4.69
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175

Разделение функционала между слоями MVVM на примере создания простого WPF приложения с БД

10.02.2024, 00:12. Показов 8641. Ответов 182
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Тема создана разделением темы Вывод на печать изображения MVVM


Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вы имеете - некое свойство может иметь значения разных типов (или даже одного типа) и View выводит разные представления для разных значений, то это снимает часть противоречий.
Да про это. например в
XML
1
 <ContentControl Grid.Column="1" Content="{Binding CurrentView}"></ContentControl>
идет привязка к свойству CurrentView, оно же изменяется при переключение RadioButton. То есть от выбранного RadioButton зависит какой контент будет у ContentControl. Получается что представление очень зависимо от свойства CurrentView.

Кликните здесь для просмотра всего текста
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
public class MainWindowVM : ViewModelBase
    {
        public MainWindowVM()
        {
            //Создаём команды
            OpenUserControl1Command = new RelayCommand(OpenUserControl1);
            OpenUserControl2Command = new RelayCommand(OpenUserControl2);
            OpenUserControl3Command = new RelayCommand(OpenUserControl3);
 
            OpenOtherControlCommand = new RelayCommand(OpenOtherControlCommandExecute);
        }
        #region открытие user control
        private object _popupCurrentView;
 
        public object PopupCurrentView
        {
            get => _popupCurrentView;
            set
            {
                _popupCurrentView = value;
                OnPropertyChanged(nameof(PopupCurrentView));
            }
        }
        public ICommand OpenOtherControlCommand { get; private set; }
        public void OpenOtherControlCommandExecute(object obj) => PopupCurrentView = new SelectLangue();
 
        public ICommand CloseOtherControlCommand { get; private set; }
        public void CloseOtherControlCommandExecute(object obj) => PopupCurrentView = null;
        #endregion
 
        private object _currentView;
 
        /// <summary>
        /// ListcurrentView нужен для хранения состояния UserControl. 
        /// Все действия над представлением и изменением контента сохраняются в этой коллекции. 
        /// Если хранить  представление и изменением контента не нужно. Тогда лучше удалить эту коллекцию и связанный с ней метод.
        /// </summary>
        private List<UserControl> ListcurrentView = new();
 
        /// <summary>
        /// Отображание текущего UserContol в ContentControl в окне MainWindow
        /// </summary>
        public object CurrentView
        {
            get => _currentView;
            set
            {
                _currentView = value;
                OnPropertyChanged(nameof(CurrentView));
            }
        }
        #region Команды для отображения UserControl в окне MainWindow
        public ICommand OpenUserControl1Command { get; }
        private void OpenUserControl1(object obj) => CurrentView = GetOrAddUserControl<UserControl1>();
 
        public ICommand OpenUserControl2Command { get; }
        private void OpenUserControl2(object obj) => CurrentView = GetOrAddUserControl<UserControl2>();
 
        public ICommand OpenUserControl3Command { get; }
        private void OpenUserControl3(object obj) => CurrentView = GetOrAddUserControl<UserControl3>();
 
        /// <summary>
        /// Универсальный метод для возвращения UserControl из коллекции
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private UserControl GetOrAddUserControl<T>() where T : UserControl, new()
        {
            var control = ListcurrentView.Find(c => c.GetType() == typeof(T));
            if (control == null)
            {
                control = new T();
                ListcurrentView.Add(control);
            }
            return control;
        }
        #endregion
    }


Цитата Сообщение от Элд Хасп Посмотреть сообщение
И такое переключение должно быть реализовано с помощью навигатора в View.
Использование сервисов, чтобы узнать об изменение View?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.02.2024, 00:12
Ответы с готовыми решениями:

ASP.NET MVC - разделение функционала между различными view
Добрый день)) Хочу спросить совета. В своем проекте использую MVC + jQuery, чтобы создать функционал в системе, аналогичный тому, что...

WPF MVVM: варианты создания VM с параметрами
Есть обычная ViewModel: public class SomeViewModel { private readonly ILogger logger; private readonly...

WPF нюансы создания проводника и мелочи по MVVM
Здравствуйте. Я только начинаю осваивать WPF и паттерн MVVM, и вот в чём загвостка: 1) Я уже написал визуальное оформление приложения и...

182
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
27.02.2024, 10:41
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ну.... и да, и нет.
Если там только строка подключения - это одно.
А если изменения типа Хранилища, его архитектуры, то изменение строки подключения в настройках приложения не всегда хватит.
В данном случае - это детали реализации Репозитория, которые по большому счёту к рассматриваемой ьтеме не имеют отношения. Важно только чтобы детали реализации Репозитория не влияли на другие слои.
Вы в своём примере поменяли имя БД - это не относится к реализации хранилища, репозитория и т.д, это относится только к строке подключения. Просто пример не удачный привели...
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
27.02.2024, 10:42
Цитата Сообщение от xellan24rus Посмотреть сообщение
есть эта ссылка будет доступна для всех решений, но изменения едины для всех проектов если изменить UserRepository и т.п
Нет.
В интерфейсе Модели экземпляр UserRepository будет предоставляться чрез интерфейс IRepository<Person>.
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
27.02.2024, 11:04
xellan24rus, Вот так Application связывает все контракты и реализации
C#
1
2
3
4
5
6
7
8
9
10
services
    .AddSingleton(Current.Configuration)
    .AddSingleton<IMainDA, MainDA>()
    .AddSingleton<IViewModelsService, ViewModelsService>()
    .AddSingleton<IWindowService, WindowService>()
    .AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>()
    .AddSingleton<IViewModelFactory, ViewModelFactory>()
    .AddTransient<IMainWindowVM, MainWindowVM>()
    .AddTransient<ICPSAddSpecificationDetailDialogVM, CPSAddSpecificationDetailDialogVM>()
    .AddTransient<ICPSContractEditDialogVM, CPSContractEditDialogVM>();
Если что-то меняется в реализации, остальной код даже этого не заметит, так как он работает через интерфейс, если что-то меняется в контракте то реализация должна быть исправлена под новый тип.

Добавлено через 19 минут
xellan24rus, А вот так идёт взаимодействие остальных объектов с контрактами
C#
1
2
3
4
5
6
7
8
9
10
public MStorageDataInputWindowVM(IWindowService windowService,
                                 IBackgroundTaskQueue taskQueue,
                                 IMainDA mainDA,
                                 IViewModelFactory viewModelFactory)
{
    _windowService = windowService;
    _taskQueue = taskQueue;
    _mainDA = mainDA;
    _viewModelFactory = viewModelFactory;
}
И им абсолютно фиолетово кто и как реализует этот контракт.
1
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 11:16  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Должна быть точка развязки сильных связей.
Это может быть интерфейс, может быть базовый (абстрактный класс). Но он должен быть в отдельной сборке от его реализации. Иначе не получится убрать сильные связи между слоями.
Как будет время (на выходных скорее всего) - я покажу в своей ветке, как это нужно сделать.
Для этого не требуется много времени - время требуется для вникания в проект, так как просто забываю что и как там. В том числе введение контрактов, вместо сильных связей, очень сильно экономит время для сторонних разработчиков необходимое для вникание в решение.
Хорошо, тогда пока что не буду лезть, так как не то сделаю скорее всего

Добавлено через 5 минут
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В интерфейсе Модели экземпляр UserRepository будет предоставляться чрез интерфейс IRepository<Person>.
Но IRepository<Person> явно лишний, ведь зачем реализовывать свойства Person(У меня в проекте People изначально было и так же и сейчас ) Так как у меня в проекте класс
C#
1
public class Command<T> : IRepository<T> where T : class
Сделан для работы с базовыми функциями хранилища, при желании расширить его не проблема.
И так как при создании
C#
1
Command<People> people = new Command<People>();
у people все свойства будут доступны и помимо них, все команды для работы с хранилищем.
То есть реализация IRepository<Person> при данной реализации лишняя, это приведет к дублированию кода только. Вчера описывал это, почему не стал так делать.

Добавлено через 1 минуту
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Вот так Application связывает все контракты и реализации
Удобно по своему, почитаю про это для саморазвития.

Добавлено через 2 минуты
Цитата Сообщение от Элд Хасп Посмотреть сообщение
я покажу в своей ветке, как это нужно сделать.
Только перед этим обновите свою ветку на реализацию моей. Я внесу еще немного правок и в целом сейчас моя ветка сильно отличается от вашей
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
27.02.2024, 11:18
Цитата Сообщение от xellan24rus Посмотреть сообщение
Удобно по своему, почитаю про это для саморазвития.
Так работает Microsoft.Extensions.DependencyInjection, хорошая вещь
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 11:25  [ТС]
Andrey-MSK, почитаю. Как я понял объект класса тесно связан с интерфейсом. И тогда для Vm нужно будет писать свой интерфейс. А для репозитория реализовывать другие интерфейсы если это нужно. Получается что практически всё строго завязано на интерфейсах
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
27.02.2024, 11:30
Цитата Сообщение от xellan24rus Посмотреть сообщение
Получается что практически всё строго завязано на интерфейсах
Ага. Вы передаёте в сервис интерфейс и его реализацию, далее в нужном месте внедряете это в нужный объект
C#
1
.AddTransient<IMainWindowVM, MainWindowVM>()
И в этом объекте объявляете нужные поля для работы с этими интерфейсами
C#
1
2
3
4
private readonly IWindowService _windowService;
private readonly IBackgroundTaskQueue _taskQueue;
private readonly IMainDA _mainDA;
private readonly IViewModelFactory _viewModelFactory;
И внедряете реализацию через конструктор этого объекта
C#
1
2
3
4
5
6
7
8
9
10
public MStorageDataInputWindowVM(IWindowService windowService,
                                 IBackgroundTaskQueue taskQueue,
                                 IMainDA mainDA,
                                 IViewModelFactory viewModelFactory)
{
    _windowService = windowService;
    _taskQueue = taskQueue;
    _mainDA = mainDA;
    _viewModelFactory = viewModelFactory;
}
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
27.02.2024, 11:45  [ТС]
Andrey-MSK, понял, хостирование приложения и внедрение зависимостей, не понял только как тут навигация работает, по окнам-страницам.
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
27.02.2024, 14:45
xellan24rus, Не знаю про навигацию, но вот так достаются нужные VM из сервисов
C#
1
2
3
4
5
6
7
namespace Services.Interfaces
{
    public interface IViewModelFactory
    {
        T CreateViewModel<T>() where T : IBaseViewModel;
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
 
using Microsoft.Extensions.DependencyInjection;
 
using Services.Interfaces;
 
namespace DBClient.Services
{
    public class ViewModelFactory : IViewModelFactory
    {
        private readonly IServiceProvider _serviceProvider;
 
        public ViewModelFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
 
        public T CreateViewModel<T>() where T : IBaseViewModel
            => _serviceProvider.GetService<T>();
    }
}
Применение в VM
C#
1
2
3
4
5
6
7
8
9
10
11
12
private void ShowMiMReport()
{
    // Получаем нужную VM из сервисов
    IMiMReportWindowVM vm = _viewModelFactory.CreateViewModel<IMiMReportWindowVM>();
 
    // Заполняем нужные для её работы свойства
    vm.Branch = _branch;
    vm.CurrentEObject = SelectedEObject;            
 
    // Сервисом управления окнами открываем нужное окно
    _windowService.ShowWindow(vm);
}
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
28.02.2024, 00:07
Цитата Сообщение от xellan24rus Посмотреть сообщение
пока что не буду лезть, так как не то сделаю скорее всего
Я скинул фиксацию.
Там не всё сделано, но направление поймёте.
По линии окна авторизации сделано всё.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
28.02.2024, 08:19
Цитата Сообщение от xellan24rus Посмотреть сообщение
пока что не буду лезть, так как не то сделаю скорее всего
Добавил фиксацию с разделением View и App.
Теперь в проекте View есть зависимость только от Common.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
28.02.2024, 17:51  [ТС]
Элд Хасп, добрался до пк наконец то =) Постепенно разбираю реализацию. Repositories вы сильно изменили, и для вызова репозитория с командами придется передать все интерфейсы которые содержат логику, но это ладно перезагрузкой конструктора можно вызывать только не обходимое. И так как сам Repositories не содержит ничего кроме ссылки на вызов команд из DataBase, то Repositories является ссылкой, в нем нет никакой логики. И теперь Repositories не зависит от DataBase, но Repositories нельзя использовать если в проекте нету зависимости DataBase.

В моей ветке Repositories зависит от DataBase, но он реализовывал логику и нужды в App делать зависимость для DataBase не было.
C#
1
private ProductRepository  Product { get; set; }
Возвращал всё что нужно через свойство Product.ProductCollections

И так как мой принцип с бд состоял при работе с использованием подхода Crud базовые реализации бд, во многих бд они есть, если придется менять бд, то нужно лишь сменить набор команд, то есть нет завязки на типах, нет зависимости в указание типа.
C#
1
2
 Product.Add(Selected); 
 public Product Add(IProduct product)
Добавлял данные зависив от интерфейса, но не от типа класса.
А ваша реализация с ProdustsRepository и PeopleRepository сильно зависит от типов, если придется сменить тип то скакать в дублях кода, я описывал ранее почему не сделал так, не люблю дубли кода если в них нет нужды.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Добавил фиксацию с разделением View и App.
Теперь в проекте View есть зависимость только от Common.
Но нету ViewModel, как теперь вызывать Vm? Для каждой Vm из интерфейса для vm создавать новую?

Добавлено через 14 минут
Цитата Сообщение от xellan24rus Посмотреть сообщение
Добавлял данные зависив от интерфейса, но не от типа класса.
эта зависимость только в репозитории ProductRepository, сам класс Command, по прежнему не имеет ни единой зависимости в плане типов

Добавлено через 6 минут
Поэтому я не понимаю, зачем делать дубли кода, ведь у вас MainModel : IRepositoriesModel имеет реализации дубликатов. А так как мы работаем с бд, а не с json, то это не оправдывает дубликаты. Но и для json можно было через рефлексию такое же в одном классе сделать, возможно даже без рефлексии получится(но это не точно)
А сами репозитории зависят от контекста.
C#
1
2
3
4
public PeopleRepository(Context context)
{
    this.context = context;
}
В моем примере для использования репозитория даже его объявлять не нужно, эти команды выполнялись строго в единственном классе.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.02.2024, 00:33
Цитата Сообщение от xellan24rus Посмотреть сообщение
то Repositories является ссылкой, в нем нет никакой логики.
Совершенно верно.
Но это из-за того что в Модели нет БЛ, кроме работы с БД.
Например, если бы это была игра, то в этой сборке была бы ещё и логика игры, а не только логика работы с Хранилищем игры.

Цитата Сообщение от xellan24rus Посмотреть сообщение
Для каждой Vm из интерфейса для vm создавать новую?
Да.
Иначе это будут сильные ссылки.

Цитата Сообщение от xellan24rus Посмотреть сообщение
А так как мы работаем с бд, а не с json, то это не оправдывает дубликаты.
А какая разница оправдывает или нет?
"Идеальная" реализация должна оправдывать только свою идеализацию.
А в таком случае Хранилищем может быть как любая БД, так и любой файл (в том числе JSON) или WEB сервер.

Никакая логика (кроме App) при этом не должна меняться.

Цитата Сообщение от xellan24rus Посмотреть сообщение
А сами репозитории зависят от контекста.
Реализации репозитория, а не его нe публичный интерфейс.
А юзают его именно через интерфейс.

Цитата Сообщение от xellan24rus Посмотреть сообщение
А ваша реализация с ProdustsRepository и PeopleRepository сильно зависит от типов, если придется сменить тип то скакать в дублях кода,
Воще, не понял.
Какой тип?
Если интерфейс - то да. придётся менять коды его использующие.
Если реализации интерфейса, то только код в сборке реализации.
В том числе не только код. Изменение реализации приводит к необходимости перекомпиляции зависящих сборок, хотя в них нет изменения кода.
А при слабых связях, такая перекомпиляция не требуется.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
29.02.2024, 17:09  [ТС]
Элд Хасп, примерно понял.
Смотрите для ослабления зависимостей то что принадлежит к бд, у вас реализовано в DataBase. Тем самым базовые реализации для работы бд лежат именно там. Если перенести в другой проект туже авторизацию, то у авторизации станет более сильная зависимость, это будет не правильно.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
"Идеальная" реализация должна оправдывать только свою идеализацию.
А в таком случае Хранилищем может быть как любая БД, так и любой файл (в том числе JSON) или WEB сервер.
В целом да, у вас PeopleRepository и ProdustsRepository имеют собственную реализацию базовой логики, отчасти это дубликат кода. Эту часть можно заменить на реализацию универсального класса, на выходе меньше одинакового кода. А для для логики уже создавать свои классы, где будет ссылка на универсальный класс с базовыми методами, остальное все логика строго только для это класса. Зависимость при этом будет слабая. Чем плох такой подход?
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Для каждой Vm из интерфейса для vm создавать новую?
Да.
Иначе это будут сильные ссылки.
Тогда удалю проект с Vm, для примера это лишнее тогда.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если интерфейс - то да. придётся менять коды его использующие.
Если реализации интерфейса, то только код в сборке реализации.
В том числе не только код. Изменение реализации приводит к необходимости перекомпиляции зависящих сборок, хотя в них нет изменения кода.
А при слабых связях, такая перекомпиляция не требуется.
Спасибо за разъяснения)
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
29.02.2024, 17:13
Цитата Сообщение от xellan24rus Посмотреть сообщение
Смотрите для ослабления зависимостей то что принадлежит к бд, у вас реализовано в DataBase. Тем самым базовые реализации для работы бд лежат именно там. Если перенести в другой проект туже авторизацию, то у авторизации станет более сильная зависимость, это будет не правильно.
Делаете нечто вот такое для своего репозитория и засовываете это всё в отдельную сборку
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
using DALibrary.DataAccess;
 
namespace DALibrary.Interfaces
{
    public interface IMainDA
    {
        CPSDataDA CPSDataDA { get; }
        DrawDA DrawDA { get; }
        DrawSpecDA DrawSpecDA { get; }
        DrawSysDA DrawSysDA { get; }
        EObjectDA EObjectDA { get; }
        ExcelDA ExcelDA { get; }
        GPlanDA GPlanDA { get; }
        LaborHBTypeDA LaborHBTypeDA { get; }
        LaborHBWorkDA LaborHBWorkDA { get; }
        MaterialDA MaterialDA { get; }
        MiMDA MiMDA { get; }
        MRDataDA MRDataDA { get; }
        NZDataDA NZDataDA { get; }
        ONZDataDA ONZDataDA { get; }
        ReportByDateDA ReportByDateDA { get; }
        ReportDA ReportDA { get; }
        SpecialDA SpecialDA { get; }
        WeldingDA WeldingDA { get; }
    }
}
И потом просто подключаете её к новому проекту, запускаете как сервис и работаете через этот интерфейс.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16152 / 11273 / 2890
Регистрация: 21.04.2018
Сообщений: 33,147
Записей в блоге: 2
29.02.2024, 17:35
Цитата Сообщение от xellan24rus Посмотреть сообщение
В целом да, у вас PeopleRepository и ProdustsRepository ... Чем плох такой подход?
Это норм.
Детали реализации - не важны.
Проблема вашего Command<T> была в том, что он публичный.
Если сделать её внутренний, а через публичную "морду" предоставлять только Command<Person> и Command<Product> - тоже было бы нормально.
То есть нужно ограничить T только теми классами для которых он реализован.

Добавлено через 2 минуты
Цитата Сообщение от xellan24rus Посмотреть сообщение
Если перенести в другой проект туже авторизацию, то у авторизации станет более сильная зависимость, это будет не правильно.
Покажу пример, как будет время.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
29.02.2024, 17:50  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Делаете нечто вот такое для своего репозитория и засовываете это всё в отдельную сборку
Это отчасти понял, сейчас правлю проект, поэтому пока что нечего показать для сравнения =\
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Проблема вашего Command<T> была в том, что он публичный.
Если сделать её внутренний, а через публичную "морду" предоставлять только Command<Person> и Command<Product> - тоже было бы нормально.
То есть нужно ограничить T только теми классами для которых он реализован.
Вот оно в чём дело, я сейчас свое решение правлю, ослабляю ссылки.
Вышло не что такое

Так как это базовые реализации, то объявил как у вас в Data Base, чтобы не было зависимости от других проектах, так как логики толком нету кроме загрузки данных, то в проекте репозитория мне создать класс с ссылкой на реализацию из Data Base и в этом же классе сделать загрузку данных. А в Vm мне остается только вызвать этот класс и все.
Тогда я всё верно сделаю?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Покажу пример, как будет время.
Хорошо, но смотрите как так авторизация зависит от класса User то зависимость идёт только от бд, в других проектах если делать, то будет зависимость от них. Тогда лучше реализовать интерфейс в новом проекте, чтобы не было лишних зависимостей.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3451 / 2772 / 575
Регистрация: 04.09.2018
Сообщений: 8,716
Записей в блоге: 3
29.02.2024, 18:05
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
MiMDA MiMDA { get; }
MRDataDA MRDataDA { get; }
NZDataDA NZDataDA { get; }
Прям музыка....
1
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3451 / 2772 / 575
Регистрация: 04.09.2018
Сообщений: 8,716
Записей в блоге: 3
29.02.2024, 18:12
Цитата Сообщение от xellan24rus Посмотреть сообщение
Вышло не что такое
В итоге, у тебя должно получится нечто такое:
Кликните здесь для просмотра всего текста

, где центральная точка ничего ни о ком не знает.
0
 Аватар для xellan24rus
364 / 296 / 55
Регистрация: 08.04.2020
Сообщений: 1,175
29.02.2024, 20:16  [ТС]
Цитата Сообщение от wizard41 Посмотреть сообщение
где центральная точка ничего ни о ком не знает
Осталось только сделать такое)

Добавлено через 34 минуты
Элд Хасп, обновил ветку на то что успел сделать пока что. Навигатор не делал особо со view. Посмотрите связи репозитория ослабил более менее или нет? Vm тоже не затронул пока что
Цитата Сообщение от Элд Хасп Посмотреть сообщение
То есть нужно ограничить T только теми классами для которых он реализован.
Но тогда придется код дублировать, ведь ссылочные типы будут разные для ef. А вариант без дубликатов с ограничениями наверное не получится сделать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.02.2024, 20:16
Помогаю со студенческими работами здесь

Структура WPF приложения на MVVM
Здравствуйте. Разрабатываю приложение на WPF. Использую шаблон MVVM. В представлении контент сгруппирован по вкладкам TabControl. ...

Пример реализации WPF+MVVM приложения
Тема из цикла https://www.cyberforum.ru/wpf-silverlight/thread2384523.html Пример решения ТЗ по теме...

Паттерн MVVM или как писать приложения на WPF
Собтвенно вопрос в заголовке. По-скольку WPF поддерживает привязку различным образом наверно это нужно как-то использовать, а не просто как...

Kivy для создания простого приложения
Всем привет ,я делаю простую программу на python, но никак не могу решить 2 проблемы. 1) Никак не меняется фон ModalView, хотя уже все...

Пример переключения между окнами WPF MVVM
Здравствуйте. Изучаю как можно переходить между окнами в wpf в рамках MVVM. Изучаю данный пример: ...


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

Или воспользуйтесь поиском по форуму:
120
Ответ Создать тему
Новые блоги и статьи
Транскрипция 55-минутного видео через Whisper: WhisperDesktop облажался, спас Google Colab[
anaschu 01.06.2026
Понадобилось получить текст из свежезагруженного видео на YouTube. Казалось бы, задача на пять минут. Заняла полтора часа. Делюсь опытом — может кому пригодится последовательность решений. . . .
21 мат мед. Планы на развитие модели здравоСохранения
anaschu 01.06.2026
AnyLogic: план развития симуляционной модели рабочего коллектива — динамический абсентеизм, реальные данные, три сценария сравнения Продолжаю серию постов о дискретно-событийной модели рабочего. . .
20. Мат мед. Абсентеизм как отдельный тип простоя
anaschu 29.05.2026
Апдейт модели: исправленные баги, абсентеизм и новые механизмы Продолжаю развивать ранее описанную модель рабочего коллектива на AnyLogic. За последние несколько дней был проведён серьёзный. . .
19. здоровье, усталость и психотип работника влияют на производительность предприятия, и наоборот, производительность на здоровье, усталось и психотип
anaschu 28.05.2026
Дискретно-событийная модель рабочего коллектива на AnyLogic: здоровье, выгорание, психотипы и микростимуляция Привет, коллеги. Хочу поделиться итогами нескольких недель работы над симуляционной. . .
"Прокси" для последовательного порта
Eddy_Em 28.05.2026
Эту штуку написал я достаточно давно. Но сейчас вот понадобилось настроить датчик грозы, но при этом не отключать его от "метеодемона". Соответственно, надо запустить этот "прокси": метеодемон будет. . .
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru