I have my MainView and an associated MainViewViewModel which are linked by ViewModelLocator.
Within MainViewViewModel there is a command which should trigger a new Window to open which has it's own View and ViewModel (NewView and NewViewViewModel).
In a lot of the examples I've seen it is suggested to use Mvvmlight's Messenger to do something like this:
public class MainViewViewModel
{
private void OpenNewWindow()
{
Messenger.Default.Send(new NotificationMessage("NewView"));
}
}
And then register the NewViewViewModel and handle the message like this:
public class NewViewViewModel
{
public NewViewViewModel()
{
Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
}
private void NotificationMessageReceived(NotificationMessage obj)
{
if (obj.Notification == "NewView")
{
NewView view = new NewView();
view.Show();
}
}
}
However, this doesn't work because the NewViewViewModel isn't yet instantiated (so isn't registered with Messenger). Additionally, this doesn't fit with MVVM because NewViewViewModel is responsible for creating NewView.
What is the correct way to achieve a simple command which instantiates and opens a new View and ViewModel pair which are linked via ViewModelLocator and setting of DataContext="{Binding NewView, Source={StaticResource Locator}}" in NewView.xml?
Use a window service:
MVVM show new window from VM when seperated projects
You may either inject the view model to with an IWindowService implementation or use a static WindowService class:
public static class WindowService
{
public static void OpenWindow()
{
NewView view = new NewView();
view.Show();
}
}
Dependency injection is obviously preferable for being able to unit test the view model(s) and switch implementations of IWindowService at runtime.
My current class PropertyManager looks like this:
public class PropertyManager : IDisposable
{
private readonly IPropertyRepo _propertyRepo;
private readonly IUserTypeRepo _userTypeRepo;
public PropertyManager(IPropertyRepo propertyRepo, IUserTypeRepo userTypeRepo = null)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
_propertyRepo = propertyRepo;
if (userTypeRepo != null)
_userTypeRepo = userTypeRepo;
}
}
My Property Manager will use the _userTypeRepo in some method to accomplish some task. I think I want to implment a rule that says "Each Manager(Service,Factory,etc) should be responsible for its own repository."
The idea:
The PropertyManager, because it needs to do something with the UserTypeRepo, I should be using the UserManager for such activities.
As such, this means that I will not provide a repo when creating an instance of the UserManager (i.e., var usrMgr = new UserManager(); // no repo). Instead, the UserManager will use the default constructor which will create a new instance of the IUserTypeRepo and provide a new instance of a UserManager and then it can do its work.
I think this accomplishes some design principle such as Separation of Concerns and the Single Responsibility, but then I may be getting away from my Dependency Injection design pattern as the new Managers would now have multiple constructors and look like this:
public class PropertyManager : IDisposable
{
private readonly IPropertyRepo _propertyRepo;
public PropertyManager(){
// use the default repo
_propertyRepo = new PropertyRepo();
}
// Used from Controller or Unit Testing
public PropertyManager(IPropertyRepo propertyRepo)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
}
}
public class UserManager : IDisposable
{
private readonly IUserRepo _userRepo;
public UserManager(){
// use the default repo
_userRepo = new UserRepo();
}
// Used from Controller or Unit Testing
public UserManager(IUserRepo userRepo)
{
if (userRepo == null)
throw new ArgumentNullException("userRepo");
}
}
Would this be frowned upon? Or am I on the right track? In either case, why and thanks?
Update. After reading Yawar's post I decided to update my post and I think I have a relevant concern.
Let's think of a real world example of the above. I have a PropertyManager in real life named "Robert" one of the jobs he performs each morning at work is to Open() the Property (i.e., he unlocks the Property he is the Manager of). I also have a UserManger who manages people who visit the Property and her name is "Sarah" she has a function that she does called EnterProperty() (which is what she does in the morning when she physically walks into the building).
Rule: UserManager has a dependency on PropertyManager when using the EnterProperty()
This looks like this according to all accepted standards:
Property Manager
class PropertyManager : IPropertyManager
{
private readonly IPropertyRepo _propertyRepo;
public PropertyManager(IPropertyRepo propertyRepo)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
this._propertyRepo = propertyRepo;
}
// this is when Robert opens the property in the morning
public void Open()
{
_propertyRepo.Open();
}
// this is when Robert closes the property in the evening
public void Close()
{
_propertyRepo.Close();
}
// this answers the question
public bool IsOpen()
{
return _propertyRepo.IsOpen();
}
}
User Manager
class UserManager : IUserManager
{
private readonly IPropertyRepo _propertyRepo;
private readonly IUserRepo _userRepo;
public UserManager(IUserRepo userRepo, IPropertyRepo propertyRepo = null)
{
if (userRepo == null)
throw new ArgumentNullException("userRepo");
this._userRepo = userRepo;
if (propertyRepo != null)
this._propertyRepo = propertyRepo;
}
// this allows Sarah to physically enter the building
public void EnterProperty()
{
if(_propertyRepo.IsOpen())
{
Console.WriteLine("I'm in the building.");
}else{
_propertyRepo.Open(); // here is my issue (explain below)
Console.WriteLine("Even though I had to execute the Open() operation, I'm in the building. Hmm...");
}
}
}
Web API Controller
{
public void OpenForBusiness(){
private const IPropertyRepo propertyRepo = new PropertyRepo();
private IPropertyManager propertyManager = new PropertyManager(propertyRepo);
private IUserManager userManager = new UserManager(new UserRepo(), propertyRepo);
// Robert, the `PropertyManager`, opens the `Property` in the morning
propertyManager.Open();
// Sarah, the `UserManager`, goes into `Property` after it is opened
userManager.EnterProperty();
}
}
Now, everything is cool and I can walk away and I now have a Repository Pattern which use Dependency Injection which supports TDD and not tightly coupled classes among other benefits.
However, is the truly realistic? (explain why I ask in second)
I think a more real-world (realistic) approach is one that does:
Web API Controller
public void Method1()
{
private IPropertyManager propMgr = new PropertyManager(new PropertyRepo());
private IUserManager userMgr = new UserManager(new UserRepo()); // no dependencies on any repository but my own
// 1. Robert, the `PropertyManager`, opens the `Property`
propMgr.Open();
// 2. Check to see if `Property` is open before entering
// choice a. try to open the door of the `Property`
// choice b. call or text Robert, the `PropertyManager`, and ask him if he opened the `Property` yet, so...
if(propMgr.IsOpen()){
// 3. Sarah, the `UserManager`, arrives at work and enters the `Property`
userMgr.EnterProperty();
}else{
// sol, that sucks, I can't enter the `Property` until the authorized person - Robert - the `PropertyManager` opens it
// right???
}
}
the EnterProperty() method on the UserManager now looks like this:
// this allows Sarah to physically enter the building
public void EnterProperty()
{
Console.WriteLine("I'm in the building.");
}
The promised explanation from above:
If we think in real-world terms we must agree that the later is preferred over the former. When thinking of a Repository lets say this is the definition of ones self (i.e., one's Person) (i.e., the UserRepo having all the data related to the User, is to the UserManager as the DNA, Heartbeat, Brain Wave Pattern, etc. is to a Human (the HumanRepo). As such, allowing the UserManager to know about the PropertyRepo and having access to its Open() method violates all Real-World security principles and Business Rules. In reality this says that through My Contructor() I can get an Interface Representation of a PropertyRepo that I can use any way I see fit. This is synonymous to the following logic of the HumanRepo:
I, Sarah - a UserManager - through a new instance of myself with the satisfaction of the PropertyRepo through my Constructor() create a Hologram Interface of Robert, the PropertyManager that I can use any way I see fit. Granted right now I only want to use the IsOpen() method of the PropertyRepo I actually use the Open() method to do it myself if Robert has not yet performed his duty. This is a security concern to me. In the real-world this says I don't have to wait for Robert to open the Property and use the Holocopy of him and implement his Open() method to get access.
That doesn't seem right.
I think with the last implementation I get SoC, SRP, DI, Repository Pattern, TDD, and Logical Security and as close to a real-world implementation as possible.
What do you all think?
I think I agree with your SoC and breaking the PropertyManager class into PropertyManager and UserManager classes. You are almost there.
I would just refactor as shown below:
public class PropertyManager : IDisposable, IPropertyManager
{
private readonly IPropertyRepo _propertyRepo;
// Used from Controller or Unit Testing
public PropertyManager(IPropertyRepo propertyRepo)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
this._propertyRepo = propertyRepo;
}
}
public class UserManager : IDisposable, IUserManager
{
private readonly IUserRepo _userRepo;
// Used from Controller or Unit Testing
public UserManager(IUserRepo userRepo)
{
if (userRepo == null)
throw new ArgumentNullException("userRepo");
this._userRepo = userRepo;
}
}
Note: Just extract IPropertyManager & IUserManager so that the calling classes will depend upon the interfaces and provide the implementation.
Creating parameterless constructor is useless if you want to (you should) force the client to provide the concrete implementation of IPropertyRepo and IUserRepo interfaces.
public PropertyManager(){
// use the default repo
_propertyRepo = new PropertyRepo();
}
I dont think you would need
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
or
if (userRepo == null)
throw new ArgumentNullException("userRepo");
as IPropertyRepo and IUserRepo will be resolved via a IoC at the startup of your application (say its MVC then before calling the controller IoC will resolve them) so no need to check for null. I have never checked the dependencies for null in my code.
From what you have posted here thats pretty much it.
Unit of Work pattern is used for repository layer not in the manager layer. I would delete that from the title.
Hope this helps!
I think this accomplishes some OOP goal such as Separating Concerns
and the Single Responsibility Principle.
The result is opposite. Now, PropertyManager tightly couples to PropertyRepo; previously, they were loosely coupled.
First approach is better than the latter one. However, PropertyManager and UserManager should not create other objects on which they rely to do their work. The responsibility for creating and managing object should be offloaded to IoC container.
Interfaces describe what can be done, whereas classes describe how it is done. Only classes involve the implementation details—interfaces are completely unaware of how something is accomplished. Because only classes have constructors, it follows that constructors are an implementation detail. An
interesting corollary to this is that, aside from a few exceptions, you can consider an appearance of the new keyword to be a code smell. - Gary McLean Hall
Answer for Updated Question:
In your updated question, you combine Service/Manager and somewhat Domain into a single class - PropertyManager, UserManager. It becomes personal preference.
I personally like to keep them separate. In addition, I like to use Role based and Claim based authorization. Let me use my GitHub sample project as a reference. Please feel free to clone it.
User Domain
User class is also used by Entity Framework Code First Fluent API.
public partial class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
}
User Service
public class UserService : IUserService
{
private readonly IRepository<User> _repository;
public UserService(IRepository<User> repository)
{
_repository = repository;
}
public async Task<IPagedList<User>> GetUsersAsync(UserPagedDataRequest request)
{
...
}
}
Action Method
Notice that UI related Business Logic stays at UI layer.
public async Task<ActionResult> Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
bool result = _activeDirectoryService.ValidateCredentials(
model.Domain, model.UserName, model.Password);
if (result)
{
...
}
}
...
}
you can take quite a bit of a different approach.....( ignoring your repositories, but allowing for it to be injected )
In this system, the property is only readable, with an event system to handle the mutations, the event system also has rules system which controls what mutations are allowed. This means even if you have a property object you can't mutate it without going through its rules.
This code is more conceptual. The next logical step is to use a full actor model and something like (akka.net) and you may find your repository pattern just disappearing :)
public class Property
{
public string Name { get; private set; }
private IPropertyRules _rules;
private List<User> _occupants = new List<User>();
private IEventLog _eventLog;
public Property(IPropertyRules rules, IEventLog eventLog)
{
_rules = rules;
_eventLog = eventLog;
}
public ActionResult Do(IAction action, User user)
{
_eventLog.Add(action, user);
if (_rules.UserAllowedTo(action, user, this))
{
switch (action)
{
case Open o:
Open();
return new ActionResult(true, $"{user} opened {Name}");
case Enter e:
Enter(user);
return new ActionResult(true, $"{user} entered {Name}");
}
return new ActionResult(false, $"{Name} does not know how to {action} for {user}");
}
return new ActionResult(false, $"{user} is not allowed to {action} {Name}");
}
private void Enter(User user)
{
_occupants.Add(user);
}
private void Open()
{
IsOpen = true;
}
public bool IsOpen { get; set; }
}
public interface IEventLog
{
void Add(IAction action, User user);
}
public class Enter : IAction
{
}
public interface IPropertyRules
{
bool UserAllowedTo(IAction action, User user, Property property);
}
public class Open : IAction
{
}
public class ActionResult
{
public ActionResult(bool successful, string why)
{
Successful = successful;
WhatHappened = why;
}
public bool Successful { get; private set; }
public string WhatHappened { get; private set; }
}
public interface IAction
{
}
public class User
{
}
I'm building WPF application which downloads links to articles from website and displays them in a grid.
Summary of the problem:
The problem I'm hitting is that I have downloading logic in the model which does not have access to the ObservableCollection Articles (which is defined in my ViewModel and bound to DataGrid).
How should I access this collection to update it as I'm downloading new articles (so that data grid will keep adding new ones one by one)?
Details:
Here's overview of my app which implements MVVM pattern (I cut some of the not important parts to keep it easy to read):
DisplayWindow.xaml
Is binding source to PresenterViewModel.cs and ItemSource is set to Articles which is ObservableCollection (see below)
<Grid DataContext="{Binding Source={StaticResource presenterViewModel}}">
<DataGrid ItemsSource="{Binding Articles}">
<DataGrid.Columns>
<DataGridTextColumn Header="Url" Binding="{Binding Url}"/>
...
</DataGrid.Columns>
</DataGrid>
</Grid>
it also has button which triggers downloading of the article links via
<Button Content="Download" Command="{Binding DownloadArticles, Mode=OneWay}"/>
DownloadArticles method is part of PresenterViewModel and returns instance of DownloadCommand which implements interface ICommand.
PresenterViewModel.cs
contains ObservableCollection<Article> Articles
private ObservableCollection<Article> articles;
public ObservableCollection<Article> Articles
{
get { return articles; }
set
{
articles = value;
RaisePropertyChangedEvent("Articles");
}
}
public ICommand DownloadArticles
{
get
{
return downloadCommand;
}
}
DownloadCommand contains reference to PresenterViewModel and in Execute method calls it's method DownloadArticles which calls DownloadArticles in the Article model itself.
in DownloadCommand.cs:
public void Execute(object parameter)
{
presenterViewModel.DownloadArticles();
}
Solutions I was considering:
Now, the problem is I'm in DownloadArticles method in Article.cs model and need to update Articles ObservableCollection which is part of PresenterViewModel...
how do I do that? The DownloadArticles method runs downloading logic in a separate thread.
Should I pass the reference to PresenterViewModel to the DownloadArticles method of the model?
This seems like an easy way to do it, however it just doesn't feel right - I don't think model should be coupled to the ViewModel and in this case one of the methods would accept PresenterViewModel object.
Another option would be having downloading logic directly in PresenterViewModel, but that doesn't feels right either as I'd prefer my ViewModel to be lightweight and not containing any logic.
What would be the best solution in this case? If you think my architecture is fundamentally wrong, please let me know what would be the best way of structuring it in this case.
I really appreciate your advices on this!
Now, the problem is I'm in DownloadArticles method in Article.cs model
and need to update Articles ObservableCollection which is part of
PresenterViewModel... how do I do that?
What you need to do is to separate your data access logic into another layer and inject it into your ViewModel as a dependency. By doing so you won't couple any of data access logic to your ViewModel because its task should be only to expose Model to the View and respond to user input.
Suppose that your model looks something like this:
public class Article : INotifyPropertyChanged
{
private string _url;
public string Url
{
get
{
return _url;
}
set
{
_url = value;
PropertyChanged("Url");
}
}
}
All the data access logic goes to a separate layer which I will call DataService. Its job is to access the external resource and download articles:
public interface IDataService
{
IList<Article> DownloadArticles();
}
public class DataService : IDataService
{
public IList<Article> DownloadArticles()
{
var articles = new List<Article>();
// you actually download articles here
return articles;
}
}
The data access layer is then injected in your ViewModel
public class PresenterViewModel : BaseViewModel
{
private readonly IDataService _dataService;
public PresenterViewModel(IDataService dataService)
{
_dataService = dataService;
}
}
Finally when user requests to download articles by triggering DownloadCommand you delegate this job to your service and wait for result which then will be exposed to your View by ObservableCollection<Article> Articles property of your ViewModel:
// your DownlodArticles command's execute method
public void Execute(object parameter)
{
var articles = _dataService.DownloadArticles();
Articles = new ObservableCollection(articles);
}
If for some reason you don't want to use dependency injection, you can implement your DataService as singleton and call it from your ViewModel:
public class DataService
{
private static DataService _instance;
public static DataService Instance
{
get
{
if (_instance == null)
{
_instance = new DataService();
}
return _instance;
}
}
public IList<Articles> DownloadArticles()
{
// ...
}
}
public void Execute(object parameter)
{
var articles = _DataService.Instance.DownloadArticles();
Articles = new ObservableCollection(articles);
}
UPDATE:
Your data service GetArticles method:
public Task DownloadArticles(ICollection<Article> articles)
{
// clear the collection if neccessary
articles.Clear();
return Task.Run(() =>
{
// load articles one by one and add them to the collection
}
}
Your ViewModel command execute method:
private async void Execute(object parameter)
{
await _dataService.LoadArticles(Articles);
}
My ExampleViewModel has a parameter (a model) that it needs to function properly. I also have a list variant of the ExampleViewModel that just contains a ObservableCollection<ExampleViewModel> and has some wrapper methods.
The issue shows it self when I try to use dependency injection with MVVM Light. Let me explain the scenario with some code.
default ViewModelLocator:
public class ViewModelLocator {
public ViewModelLocator() {
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic) {
SimpleIoc.Default.Register<IDataService, DesignDataService>();
} else {
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main {
get {
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public static void Cleanup() {}
}
Simple MainViewModel:
public class MainViewModel : ViewModelBase {
private IDataService _service;
private MainModel _model;
// Goal. I think?
public MainViewModel(IDataService service, MainModel model) {
_service = service;
_model = model;
}
// Used now
public MainViewModel(MainModel model) {
_service = ServiceLocator.Current.GetInstance<IDataService>();
_model = model;
}
}
And the ListMainViewModel fills it's list like this:
Mains = new ObservableCollection<MainViewModel>(
_service.GetAll().Select(model => new MainViewModel(model))
);
Because of the list creation in the ListMainViewModel I can't inject the data source in the constructor and have to use it as shown under // Used now. Which is fine, but when I try to unit test problems occur, as you can probably imagine.
I use a unit test like this at the moment:
public void ListMainViewModel_DoSomething_Success() {
// Arrange
var mock = new Mock<IDataService>();
mock.Setup(m => m.Create(new MainModel { Naam = "Create" }));
mock.Setup(m => m.Update(new MainModel { Naam = "Update" }));
var listMainViewModel = new ListMainViewModel(mock.Object);
var selected = new MainModel() { Prop = "Test" };
listMainViewModel.SelectedMainViewModel = new MainViewModel(selected);
// Act
listMainViewModel.DoSomething();
// Assert
mock.Verify(x => listMainViewModel.DoSomething(), Times.Exactly(1));
}
Note: Not sure if the unit test is correct. But the problem occurs while creating the SelectedMainViewModel because it doesn't fetch a DataService.
For now I have two choices (I think), I can make the MainModel in MainViewModel optional, which is not something that should be possible and contructor inject the IDataService. Or I can discover a way to make the _service find-able by the MainViewModel.
Is there any elegant way to solve this? Because I have the feeling I have to make some hack using if (InDesignMode) or something similar.
You mention that:
I can't inject the data source in the constructor and have to use it as shown under // Used now.
What are you seeing when you try this? What exception is thrown? Why doesn't the below work?
Mains = new ObservableCollection<MainViewModel>(
_service.GetAll().Select(model => new MainViewModel(model, _service))
);
I think it may help if you get away from using a service locator, which looks to be an anti-pattern for your goal. When using a DI container, it's best to create the entire object graph at the application start or web request (for web apps). But here you are using the new keyword to create your MainViewModel.
See this post.
I'm currently trying out some MVP patterns sample and I have been told not create concrete Presenter objects in the View. Is there any way to have Presenter objects created dynamically ?
public partial class View: Window, IView
{
private Presenter _presenter;
public View()
{
InitializeComponent();
_presenter = new Presenter(this); //Asked to avoid this
}
}
You're thinking it wrong. You don't create the presenter in the view. You create it elsewhere (application startup, other presenters) and it passes itself to the view, either as a constructor parameter, or by setting a property.
Like this:
class FooView : IFooView
{
private readonly IFooPresenter presenter;
public FooView(IFooPresenter presenter)
{
this.presenter = presenter;
}
}
class FooPresenter1 : IFooPresenter
{
private readonly IFooView view;
public FooPresenter1()
{
view = new FooView(this);
}
}
// or
class FooPresenter2 : IFooPresenter
{
private readonly IFooView view;
public FooPresenter2(IFooView view)
{
this.view = view;
view.Presenter = this;
}
}
And by the way, you seem to be using WPF. If that's the case you may want to have a look at the Model-View-ViewModel pattern instead.
With view first creation you can use an IoC container to create your Presenter:
public View(IMyPresenter presenter)
{
InitializeComponent();
_presenter = presenter;
}
Alternatively, you can use model (presenter) first where the View is passed to the Presenter in much the same way. See Which came first, the View or the Model? for discussion on this topic.
Or you could use a third object to bind the View and Presenter together, like the IBinder service in Caliburn.