Распределение ответственности между основной VM и диалоговой
Допустим, у нас есть UsersViewModel - VM для отображения списка пользователей и добавления их.
internal class UsersViewModel : ViewModelBase
{
public ReactiveCommand<Unit, Unit> AddUserCommand { get; }
public UsersViewModel()
{
AddUserCommand = ReactiveCommand.CreateFromTask(AddUserAsync);
}
private async Task AddUserAsync()
{
//Что-то делаем
}
}
Для добавления пользователя вызывается AddUserDialogViewModel - диалоговое окно.
internal class AddUserDialogViewModel : DialogViewModelBase
{
//Какие-то свойства пользователя
public ReactiveCommand<Unit, Unit> CancelCommand { get; }
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
public AddUserDialogViewModel()
{
CancelCommand = ReactiveCommand.Create(Cancel);
SaveCommand = ReactiveCommand.CreateFromTask(SaveAsync);
}
private void Cancel()
{
//Отменяем добавление и возвращем DialogResult.Cancel
}
private async Task SaveAsync()
{
//Каким-либо образом добавляем пользователя
}
}
И вот тут начинается мой вопрос. Как с точки зрения SOLID правильно сделать это добавление?
За все время я нашел всего 2 способа:
- Напрямую пробросить класс IUSerService в DialogViewModel через конструктор и чтобы уже внутри вызывались нужные методы.
internal class AddUserDialogViewModel : DialogViewModelBase
{
private readonly IUserService _userService;
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
public AddUserDialogViewModel(IUserService userService)
{
SaveCommand = ReactiveCommand.CreateFromTask(SaveAsync);
}
private async Task SaveAsync()
{
await _userService.AddAsync();
}
}
На первый взгляд выглядит логично, но должно ли диалоговое окно знать вообще каким образом происходит добавление пользователя? На мой взгляд, эта VM должна собрать нужные данные именно для добавления и отдать их кому-то, и на этом заканчивается её зона ответственности.
- Пробросить в конструктор делегат.
internal class UsersViewModel : ViewModelBase
{
private readonly IUserService _userService;
public UsersViewModel(IUserService userService)
{
_userService = userService;
}
private async Task AddUserAsync()
{
var handler = async () =>
{
await _userService.AddAsync();
};
var vm = new AddUserDialogViewModel(handler);
}
}
internal class AddUserDialogViewModel : DialogViewModelBase
{
private Func<Task> _handler;
public AddUserDialogViewModel(Func<Task> handler)
{
_handler = handler;
}
private async Task SaveAsync()
{
await _handler();
}
}
Этот способ мне нравится больше, т.к я скрываю реализацию.