Greedy construction and dependency injection - c#

For a project I am working on, I decided to adopt the MVVM pattern.
My viewmodel needs to launch many different dialogs, which do more than just simply show OK or Cancel buttons. Most dialogs have a listview to select an item from.
To keep the viewmodel "lookless" I am injecting the different dialogs as interfaces in the viewmodel constructor.
public ContractsData(IWindow ProjectSelector, IWindow ContractSelector, IWindow DebtorSelector)
{
//.....
//.....
m_ProjectSelector = ProjectSelector;
m_ContractSelector = ContractSelector;
m_DebtorSelector = DebtorSelector;
}
With IWindow being:
public interface IWindow
{
void Close();
bool? ShowDialog();
void SetOwner(object window);
bool? DialogResult { get; set; }
object DataContext { get; set; }
}
However nice it is to be able to separate data from views from a testing point of view, all possibly needed dialog windows have to be present and fully constructed upon construction of the viewmodel, which goes against one of my principles, that of "lazy initialisation": only construct an object when you need it.
As my viewmodel grows, it will possibly need a whole bunch of dialogs, which will all be created up front and sleeping in memory until needed, which very well may never be.
I was thinking of replacing the actual dialogs with lightweight "Factory" objects, that construct the dialogs on request from the view, but I am looking for a better solution to solve the memory issues with dependency injection.

If you're using a dependency injection container, most of them will be having a feature to inject Lazy<T>. So instead of IWindow you could take dependency on Lazy<IWindow>. Without any special registrations they are clever to inject Lazy<T> for you.
If you're using poor man's injection, you could manually construct Lazy<IWindow> and inject it. Otherwise Abstract factory is another good option.

Related

Proper implementation of factory pattern using DI

I've got a question about the cleanest way for constructing new instances of some abstraction in a factory using Dependency Injection. The thing is that I use some presenter which opens it's views multiple times, but when we only "close" some view, it's being disposed, and to open the view again I need to get a new View instance once again and then I can open it.
For now the "factory" looks like this:
class ViewConstructor<TView> :IViewConstructor<TView>
where TView : class, IView
{
private readonly IIocContainer _iocContainer;
public ViewConstructor(IIocContainer iocContainer)
{
_iocContainer = iocContainer;
}
public TView Construct()
{
return _iocContainer.GetInstance<TView>();
}
}
The thing is, that I know that using IocContainer anywhere but not in the composition root it a bad thing. So I'm guessing if there's some "clean" way to implement this. To sum up, i want to be able to get MULTIPLE instances of the IView from the factory.
I found an answer in the post: https://stackoverflow.com/a/17436520/4777147
It seems, that solution may be to spawn a view using "new" in the factory.
Unfortunately, in order to use generic factory, every view has to have default constructor. Otherwise you'll need specialized factories for every view.

MVVM Handling Window Management using Factory Approach

I delegate creation(showing) of my Windows to my WindowFactory, that attaches a ViewModel to the View and shows the window. It is injected into my MainViewModel Constructor parameters.
The factory itself is very simple:
public class ProductionWindowFactory : IWindowFactory
{
public void CreateNewWindow()
{
PhoneWindow window = new PhoneWindow();
{
window.DataContext = new phoneWindowViewModel();
}
window.Show();
}
}
Now, I'm aiming at implementing more functionality of my new windows, that will happen on certain button clicks IN that new window.
As I am fairly new to Factories in general, I'm struggling to grasp a certain concept:
Example:
We have a ViewA that has a ViewModelA attached to it.
That view has a button with a command attached, that tells our WindowFactory to show a new ViewB.
ViewB has a ViewModelB and a close button, that tells it to close ViewB.
Now, since we shouldn't reference our ViewB in our ViewModelB, we have to somehow let it know which view it should close.
I have come up with possible ideas / solutions, but I would really
appreciate you letting me know which one follows the MVVM and Factory
pattern "the most", and which one is usually used in such situations.
Make our ViewModelB take an instance of windowFactory that created ViewB as a parameter on initialization, and build a method in the Factory that closes ViewB and is executed through button click -> command.
Create an IWindowManager? that inherits from IWindowFactory and build a WindowManager class, that extends the capabilities of our WindowFactory, and push it in ViewModel constructors as described above.
Any other correct solution, that I am completely unaware of?
Please bear in mind, that the above is just an example. Ideally, I'd like to implement more of advanced functionality to my windows, and have an ability to create & manage multiple different ones using that one factory.
I have not attached much code, since I'm still at the stage of learning and deciding which solution should I go with.
EDIT - REGARDING POSSIBLE DUPLICATE:
My question differs from the proposed duplicate, as the other one is simply about managing of closing windows - My question is about doing that as well, but following a FactoryPattern.
I have specified very clear guidelines in what I am trying to achieve and in what ways, that are completely different from the question linked.
First of all, the answer is none. The job of a factory is to create new objects, think of it as an elaborate new operator. Also, the idea of following a pattern "the most" is problematic in and of itself. You employ patterns because they help you achieve certain goals, e.g. you employ mvvm to evade coded-ui tests as much as possible, because they are fragile, normally.
That being said, what to do with its view is completely up to the view's view model.
Example: if one view model needs to close its own window, do it with a command as illustrated in the comment. If a view has a close all-button, its view model will have a dependency on some kind of window registry that can enumerate all open windows for the close all-command to close.
When looking at your view model, try to come up with an idea of what services it needs from the rest of the application, and inject those dependencies as interfaces. When implementing the interfaces, most likely there will be classes that implement more than one, e.g. WindowManager might implement IWindowFactory and IWindowRegistry thus making it very easy to put all newly created windows into the list of open windows. The window will have a dependency on the IWindowRegistry, too, most likely, to unregister itself when it gets closed.
The duplicate was not far off. Here is a simple adaptation of the scenario in OP
interface IView {
void Close();
}
class ViewAdapter : IView {
readonly Window view;
public ViewAdapter(Window view){
this.view = view;
}
public void Close() {
view.Close();
}
}
public class ProductionWindowFactory : IWindowFactory {
public void CreateNewWindow() {
var view = new PhoneWindow();
var viewAdapter = new ViewAdapter(view)
var viewModel = new phoneWindowViewModel(viewAdapter);
//Bind
view.DataContext = viewModel;
view.Show();
}
}
If the view model wants to instruct that the view be closed it can ask the injected contract to do so.

Correct approach when notifying ViewModels of UserControl events in WPF MVVM?

In my WPF View, I'm loading data into User Controls like this:
<ContentControl Content="{Binding ItemEditVm}" />
And then in the ViewModel:
private ItemEditViewModel _itemEditVm;
public ItemEditViewModel ItemEditVm
{
get
{
return _itemEditVm;
}
set
{
_itemEditVm = value;
OnPropertyChanged("ItemEditVm");
}
}
I've got a series of DataTemplates to say which View belongs to which ViewModel. And then in my business logic, I can just spin up a new ViewModel for the UserControl then assign it to the property and all works as expected.
However, to resolve the next task in this application, I need to be able to notify the parent ViewModel of events occurring inside the UserControl. I've done this with a simple event on my child ViewModel and a listener on the parent:
public event EventHandler ItemEditViewModelChanged();
So when I create my ViewModel I can just add a listener:
ItemEditViewModel vm = new ItemEditViewModel(itemId);
vm.ItemEditViewModelChanged += vm_ItemEditViewModelChanged;
And do what needs to be done in vm_ItemEditViewModelChanged().
However, I am instinctively uncomfortable with this. While it doesn't violate any MVVM principles direclty (things are still testable, Views and ViewModels are still separate), it doesn't seem a very flexible way of doing things and it does create undesirable logical links between ViewModel classes.
Is there a better way of doing this? Is my approach to creating and loading UserControls into ContentControls a poor way of creating child controls? Or am I worrying over nothing?
I personally prefer to implement things like this with dependency injection. Typically there will be multiple notifications that need to be made, so start by declaring an interface:
public interface ICustomEventHandler
{
void Event1();
void Event2();
// .. etc
}
Then in the child vm you use dependency injection to inject whatever object needs to watch it:
public class ChildVM
{
[Inject] public ICustomEventHandler Watcher {get; set;}
// .. etc ..
}
First of all this makes mocking very easy, so your unit tests are covered, but more importantly you've formalized the dependencies between this module and the rest of the code and also kept your options open as to how best to implement it. (A simple solution would be for the parent to implement that interface directly and inject itself into the child at creation, in another case you may need to use an intermediate class with singleton scoping or multiple clients).
I am not sure whether this work for you but just my thought.
If you have a MainViewModel which holds your all other ViewModels like the picture above then you can expose Properties/Methods to invoke MainViewModel and Let MainViewModel take the decision to talk to a different ViewModel.

Replacing ServiceLocator with DependencyInjection when implementing modal dialogs in MVVM WPF application

I am writing my first WPF application and I would like to ask you for help with a problem that I encountered.
I am trying to follow the MVVM pattern and I came to a point where I need to implement modal dialogs. I googled/read on the topic for some time and I was able to settle on a solution. However, when refactoring I encountered a dilemma that concerns using a DI (constructor injection) as a replacement of a service locator.
I am going to be referencing these: http://pastebin.com/S6xNjtWW.
I really like the approach of Roboblob:
First: He creates an abstraction of a modal dialog (interface). I named the interface IModalDialog and this is how it looks like:
public interface IModalDialog
{
bool? DialogResult { get; set; }
object DataContext { get; set; }
void Show();
bool? ShowDialog();
void Close();
event EventHandler Closed;
}
Second: An abstraction of modal dialog service:
public interface IModalDialogService
{
void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel, Action<TDialogViewModel> onDialogClose) where TDialogViewModel : class;
void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel) where TDialogViewModel : class;
}
Third: The concrete implementation of IModalDialogService:
public class ModalDialogService : IModalDialogService
{
public void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel, Action<TDialogViewModel> onDialogClose) where TDialogViewModel : class
{
// set datacontext
if (viewModel != null)
{
view.DataContext = viewModel;
}
((System.Windows.Window)view).Owner = System.Windows.Application.Current.MainWindow;
// register
if (onDialogClose != null)
{
view.Closed += (sender, e) => onDialogClose(viewModel);
}
view.ShowDialog();
}
public void ShowDialog<TDialogViewModel>(IModalDialog view, TDialogViewModel viewModel) where TDialogViewModel : class
{
this.ShowDialog(view, viewModel, null);
}
Fourth: There are more implementations of IModalDialog. Each is a Window-derived class that implements IModalDialog.
Before I ask the question (describe the problem), I need to explain this beforehand:
Let's say that I have some more services, like for example IMessageBoxService.
Then I need to declare these dependencies in the constructor of MainWindowViewModel:
public MainWindowViewModel(IModalDialogService a,
IMessageBoxService b,
...)
so that I can inject them (either by hand or using IOC container like Unity, etc.).
In order to be able to use the modal dialog service there is one missing piece of puzzle - the ability to resolve a concrete implementation of IModalDialog based on some key.
Roboblob in his article solves this last piece of puzzle using a ServiceLocator pattern:
public class Bootstrapper
{
public static void InitializeIoc()
{
SimpleServiceLocator.SetServiceLocatorProvider(new UnityServiceLocator());
SimpleServiceLocator.Instance.Register<IModalDialogService, ModalDialogService>();
SimpleServiceLocator.Instance.Register<IMessageBoxService, MessageBoxService>();
...
SimpleServiceLocator.Instance.Register<IModalWindow, EditUserModalDialogView>(Constants.EditUserModalDialog);
}
}
so he inside his MainWindowViewModel simply calls the static classes Get and resolves a concrete implementation of IModalDialog window based on a key.
Even Josh Smith uses a similar approach in his article but in comments he says that (DI - constructor injection) is a valid option.
The referenced StackOverflow answer also describes a similar WindowViewLoaderService that could be modified and use.
So the question is - what would be the best way to replace the ServiceLocator (which resolves the concrete implementations of IModalDialog) with a dependency injection?
My train of thoughts was:
One possibility is (due to the project not being very big/developed by me only) to just create a new service (e.g. called IModalDialogResolver) that would create and return new instances of concrete implementations of IModalDialog. Have all the services injected by hand.
Then I thought about an IOC container (Unity). I have no experience with it. I thought that maybe I don't have to write the IModalDialogResolver as I could register the different implementations of IModalDialog with Unity container => but then how do I use the container inside MainWindowViewModel? I cannot pass the reference to the constructor as that would be a step back to ServiceLocation.
So then I thought that maybe I can use one unity container in the bootstrapper to resolve all the services and use another one internally inside the IModalDialogResolver. But I don't know whether this is a good idea regarding the recommended usage of Unity. I really know too little to judge this. But something tells me that this is not a good idea as it creates a hidden dependency on the container + if the container is a singleton that would be equivalent to just passing the reference into the constructor.
To maybe better explain the mental block that I have: I would like to use an IOC container (e.g. Unity) to have the interfaces constructed and injected by it. But then I cannot just put IModalDialog as a parameter inside a constructor. So probably I really need to wrap this inside a service and implement myself - but then (provided that Unity can do this out of the box) it doesn't make sense to have Unity there in the first place if i cannot use it.
I know one of the alternatives is to put this one service into a base class, but for the sake of argument, let's not consider this. I really would like to learn about the right way to have this solved using dependency injection.
It's perfectly valid and expected for you to access the IoC container within your composition root.
In fact this should be the only location where you container is accessed.
In the example you've given, that's all that is happening - the concrete implementations are being registered in the container within the composition root.
So to answer your question, you don't need to replace the use of the service locator pattern here, as it's just a mechanism for registering the types in the composition root, which is perfectly valid.
If you wish to instantiate the modal dialog service based on some run time conditions, then you should inject a model dialog service factory instead (again an abstraction with an implementation registered in your container), and then the factory would have a method to create the model dialog service and this factory method would take the run time parameters required.
Your factory could then new up the appropriate model dialog service appropriately based on the run time parameters. Alternatively, it could also resolve the appropriate model dialog service from the container, which would obviously require the factory to have a reference to the container.
Most containers support automated factory types, so that you only need to define the interface for the factory, and the container will automatically implement the factory using conventions. Castle.Windsor for example has the Typed Factory Facility and Unity has some equivalents.

MVVM and DI - How to handle Model objects?

I'm using Caliburn and C#, but I feel like this is a generic MVVM/DI question.
Let's say I have a view model, NoteViewModel, that is passed a model object called Note.
Here is some code:
class NoteViewModel : PropertyChangedBase
{
private readonly Note _note;
public NoteViewModel(Note note)
{
_note = note;
}
public string Title
{
get { return _note.Title; }
set { _note.Title = value; NotifyOfPropertyChange(() => Title); }
}
}
Right now this object is created by calling new() and passing a model object.
Well, that works great, but now I need to add a method that requires an imported class from my DI container.
So do I merely call ServiceLocator.Current.GetInstance() to get it? Or should I design this view model to be created via the DI container and somehow setup a way to pass a Note object?
What is the proper way to design this view model? Basically a "PerInstance" view model that requires a model object for it's use. Does Caliburn have a built-in way to do this?
Caliburn has an interface (IHaveSubject and its typed version IHaveSubject) addressing this kind of scenario: basically it allows a mean to configure the ViewModel with a "subject" after its instantiation, tipically through the container:
class NoteViewModel : PropertyChangedBase, IHasSubject<Note> {
...
}
myNoteViewModel = ... //obtain an instance
myNoteViewModel.WithSubject(new Note());
This solution also integrates well with ISubjectSpecification / Conductor
infrastructure.
Even though post-construction initialization is a simple and effective solution, you may not want (from a pure design perspective) to renounce to an explicit constructor parameter to enforce the need for a Note to istantiate the ViewModel.
In this case I think you have to leverage peculiar features of your DI container, because you may have some parameters of the constructor representing a "real" input parameter, while other may be service dependencies.
Castle Windsor, for example, has a nice feature allowing you to quickly build an explicit (typed) factory for your ViewModel; the factory method will only allow to set the "real" parameters, while all dependencies are managed by the container (see this post for an extensive description of this Windsor feature: http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx)
Can you solve it using hierarchical view models?
To me it becomes more and more clear that I need one ViewModel per View and one ViewModel per model item or collection when building larger application.
That way we can build up ViewModels hierarchically, matching the XAML hierarchy.
The required objects can be defined or injected at the top level by app's main view model then. The nested view models can then access anything the way you design it to make things reachable by them.
About Caliburn, I don't know any specific things about that framework, sorry.
I'm using the ServiceLocator also. And I also "feel dirty" in doing this. But I have resolved to use the YAGNI principle and keep this pattern until I find a compelling payback to the complexity of adding 5 IServices into my constructors, passing them up via 3-4 layers of inheritance to the base classes in which they are needed, and creating everything via the container. Of course my app is evolving, and YAGNI doesn't always last...

Categories

Resources