Должен ли я передать View Model в мой сервис, и если да, то как это сделать? - PullRequest
0 голосов
/ 18 июня 2019

У меня есть решение, которое использует Autofac , и я переместил некоторые методы из моей модели представления в файл сервиса. Прямо сейчас я сталкиваюсь с проблемой, когда некоторые переменные в методах службы и ссылаются на свойства VM. Поэтому я понял, что, возможно, мне следует передать модель представления в службу.

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

Другое дело, что я еще не уверен, как передать виртуальную машину в службу. С моим текущим решением, которое вы можете найти ниже, я получаю исключение StackOverflow на установщика модели. Дело в том, что сейчас это лучшее, что у меня есть, и у меня нет новых идей.

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

Код будет показан на упрощенном примере. MainViewModel

public class MainViewModel : ViewModelBase
  {
        private MainViewModel _vm;
        private Person _person;
        private ISomeService _someService;
        public MainViewModel(ISomeService someService)
        {
            _person = new Person();
            _someService = someService;
            Name = "Slim Shady";
            _vm = new MainViewModel(_someService);

            Execute();
        }

        public string Name
        {
            get
            {
                return _person.Name;
            }
            set
            {
                _person.Name = value;
                OnPropertyChanged();
            }
        }

        private void Execute()
        {
            string dupa = _someService.GetTheName(_vm);
            System.Windows.MessageBox.Show(dupa);
        }
    }

Модель

public class Person
    {
        public string Name { get; set; }
    }

Услуги

public interface ISomeService
    {
        string GetTheName(ViewModel.MainViewModel _vm);
    }
    public class SomeService : ISomeService
    {

        public string GetTheName(MainViewModel _vm)
        {
            return _vm.Name;
        }
    }

Autofac

public class BootStrapper
    {
        public IContainer BootStrap()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<SomeService>()
              .As<ISomeService>().SingleInstance();

            builder.RegisterType<MainWindow>().AsSelf();
            builder.RegisterType<MainViewModel>().AsSelf().SingleInstance();

            return builder.Build();
        }
    }

UPDATE Нужно также рассмотреть ситуацию, когда некоторые другие сервисы также будут ссылаться на имя свойства Person.

Ответы [ 3 ]

2 голосов
/ 18 июня 2019

Должен ли я передать View Model в мою службу, и если да, то как это сделать?

Нет, не следует.Служба не должна зависеть от модели представления.И наоборот.

Другое дело, если передача виртуальной машины на уровень сервиса является антипаттерном, как мне ссылаться на свойство виртуальной машины из уровня сервиса?

Вы не.Служба должна возвращать любые данные, которые могут понадобиться модели представления, но она не должна ничего знать о самом типе модели представления.

В вашем примере служба должна просто возвращать строку:

public string GetTheName()
{
    return "...";
}

Если эта строка происходит из модели представления, нет смысла использовать службу для ее извлечения в первую очередь.Тогда вы можете просто получить доступ к this.Name в классе модели представления напрямую.

Если служба каким-либо образом манипулирует именем string, она должна принять string в качестве аргумента и вернуть другую строку, например:

public string GetTheName(string name)
{
    return name.Trim();
}
2 голосов
/ 18 июня 2019

Я думаю, что здесь происходит смена обязанностей.

Если ваша служба должна предоставлять данные, она должна хранить эти данные.Это не работа виртуальной машины.

Так что в вашем примере Name является свойством Person, а оно, в свою очередь, становится результатом метода получения в вашей виртуальной машине.

Я неЯ не знаю Autofac, но я думаю, что ваша служба должна содержать объект Person и предоставлять его виртуальной машине (через IoC).

Тем не менее, нам не хватает контекстной информации для полного и подходящего ответа.

Если нужно создать экземпляр Person в ВМ, вы можете просто, в ВМ, сказать своему сервису создать его экземпляр и вернуть его:

public MainViewModel(ISomeService someService)
{
    _someService = someService;
    _person = _someService.GetPerson("John");
    //etc
}

public interface ISomeService
{
    Person GetPerson(string name);
}

public class SomeService : ISomeService
{
    private List<Person> personRepository;

    //insert constructor...

    public Person GetPerson(string name)
    {
        return personRepository.Single(person => person.Name == name);
    }
}

Проще говоря, Служба не должна знатьо виртуальных машинах или даже о том, что такое виртуальная машина.

1 голос
/ 18 июня 2019

ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ

в моем слое обслуживания я создал:

public interface IPersonService
    {
        string Name { get; set; }
    }

    public class PersonService : IPersonService
    {
        Person _personModel = new Person();
        public string Name
        {
            get
            {
                return _personModel.Name;
            }
            set
            {
                _personModel.Name = value;
            }
        }
    }

и изменил:

public interface ISomeService
    {
        string GetTheName(IPersonService personService);
    }
    public class SomeService : ISomeService
    {

        public string GetTheName(IPersonService personService)
        {
            return personService.Name;
        }
    }

Так что теперь я делаю инъекцию вВ моей виртуальной машине обе службы, и при извлечении имени из SomeService я передаю впрыснутый PersonServie:

public class MainViewModel : ViewModelBase
    {
        private IPersonService _personService;
        private ISomeService _someService;
        public MainViewModel(ISomeService someService, IPersonService personService)
        {
            _personService = personService;
            _someService = someService;
            Name = "Slim Shady";

            Execute();
        }

        public string Name
        {
            get
            {
                return _personService.Name;
            }
            set
            {
                _personService.Name = value;
                OnPropertyChanged();
            }
        }

        private void Execute()
        {
            string dupa = _someService.GetTheName(_personService);
            System.Windows.MessageBox.Show(dupa);
            System.Windows.MessageBox.Show(Name);
        }
    }
...