I have a solution, that uses Autofac, and I moved some methods from my View Model to the service file. Right now I am facing a problem, where some of the variables in the service methods and refering to VM properties. So I figured out, that maybe I should pass the View Model to the Service.
First of all, I am not sure that I am supposed to do that, for separation of layers and testability. But I am guessing, that it should be no problem with mocking, correct me if I am wrong.
Another thing is that I am not sure yet how to pass the VM to Service. With my current solution, that you can find below, I am getting StackOverflow
exception on setter of the Model prop. The thing is, that right now it is the best I have and Im out of any new ideas.
Another thing, if passing a VM to the Service layer is an antipattern, how should I refer a VM property from the Service layer? Should I create some Wrapper for this, that VM and Service will refer to it?
The code will be shown on simplified example. 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);
}
}
Model:
public class Person
{
public string Name { get; set; }
}
Service:
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 Need also consider situation, where some other services will also refer to the Name property of Person.
FINAL SOLUTION
in my Service layer I created:
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;
}
}
}
and modified:
public interface ISomeService
{
string GetTheName(IPersonService personService);
}
public class SomeService : ISomeService
{
public string GetTheName(IPersonService personService)
{
return personService.Name;
}
}
So now I inject to my VM both services, and when retrieving name from SomeService
I am passing injected 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);
}
}