Распределение ответственности между основной 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 способа:

  1. Напрямую пробросить класс 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 должна собрать нужные данные именно для добавления и отдать их кому-то, и на этом заканчивается её зона ответственности.

  1. Пробросить в конструктор делегат.
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();
     }
 }

Этот способ мне нравится больше, т.к я скрываю реализацию.


Ответы (0 шт):