I'm using a custom mvp framework, that when a view is created it tries to resolve for it's correct presenter and creates a new instance of it, but the presenter needs the view for its constructor.
Is there a way to inject dependency of the view into the constructor of the presenter using simple injector?
I've tried to use lifetime scoping but, since the view resolves/creates the presenter in its own constructor it seems that it's not resolved yet when it creates the instance of the presenter, and injects a new instance and making an infite loop and a stack overflow exception
EDIT:
The code looks something like this:
public class MyView1 : IView
{
protected IPresenter<MyView> presenter;
public MyView1()
{
/// some cocde here;
presenter = ResolvePresenterBinding();
}
IPresenter<MyView> ResolvePresenterBinding()
{
//some stuff here to resolvethe apropiate Presenter and create the instance using the IOC Container
}
}
public interface IPresenter<TView> where TView : IView
{
}
public class MyPresenter1 : IPresenter<MyView>
{
IView View;
public MyPresenter1(IView view, //other dependencies here)
{
this.View = view;
}
}
Related
Background
I'm using Winforms with a MVP pattern to create an application. I'm using SimpleInjector as my IoC container. My presenters inherit from:
public interface IPresenter<TView>
{
TView View { get; set; }
}
internal class HomePresenter : IPresenter<IHomeView>
{
public IHomeView View { get; set; }
...
}
In order to create my presenters, I have decided to use a presenter factory with the following method:
public static IPresenter<TView> CreateForView<TView>(TView view)
{
var presenter = _container.GetInstance<IPresenter<TView>>();
presenter.View = view;
return presenter;
}
And then in each view, the view creates its own presenter by calling the presenter factory:
_homeMainPresenter = (HomePresenter) presenterFactory.CreateForView<IHomeView>(this);
_homeMainPresenter.View = this;
In my Program.cs file, I have:
static void Main()
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
System.Windows.Forms.Application.Run((HomeView)container.GetInstance<IHomeView>());
}
private static void Bootstrap()
{
// Create the container
container = new Container();
// Register types
container.Register<IHomeView, HomeView>(Lifestyle.Singleton);
container.Register<IPresenter<IHomeView>, HomePresenter>();
...
// Verify the container
container.Verify();
}
Problem
When the presenter factory is called from the HomeView view, the type fed into the factory is a HomeView type, not IHomeView. So, the application throws an exception because the container does not have a HomeView registration (only IHomeView). My presenters all have interfaces for the views references they store as I feel this will be better for testing. How do I avoid this situation?
Having a interface-to-implementation binding for your forms is not useful, since they are root types for your presentation technology. Most presentation technologies can't deal with custom abstractions anyway and this is the reason that you are casting your IHomeView back to HomeView to allow it to be passed on to the Application.Run method.
Instead of resolving the presenter from within the view, you can do the following instead:
public interface IHomeView { }
public interface IPresenter<TView> {
TView View { get; set; }
}
public class HomeView : Form, IHomeView
{
private readonly IPresenter<IHomeView> presenter;
public HomeView(IPresenter<IHomeView> presenter) {
this.presenter = presenter;
InitializeComponent();
}
}
Here the Form gets injected with an IPresenter<IHomeView> and stores that incoming dependency. The factory is not needed anymore and can be removed from your code.
And in your program main:
static void Main()
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
System.Windows.Forms.Application.Run(GetForm<HomeView, IHomeView>(container));
}
private static void Bootstrap()
{
// Create the container
container = new Container();
// Register types
// NOTE: We register HomeView as concrete type; not by its interface.
container.Register<HomeView>(Lifestyle.Singleton);
// Here we batch-register all presenters with one line of code and
// since the forms depend on them, they need to be singletons as well.
container.Register(typeof(IPresenter<>), AppDomain.CurrentDomain.GetAssemblies(),
Lifestyle.Singleton);
...
// Verify the container
container.Verify();
}
private static TForm GetForm<TForm, TView>() where TForm : Form, TView
{
var form = container.GetInstance<TForm>();
container.GetInstance<IPresenter<TView>>().View = form;
return form;
}
The factory class is now replaced with the GetForm method that is part of the composition root; Forms don't have access to it. The generic types allow us to resolve the proper presenter, while keeping the code type-safe.
I am building a WPF browser application with MVVM pattern.
I have a first page (ConsultInvoice) with a dataGrid. When I double click on one of the row I want to navigate to another page (EditInvoice) passing the selected row in argument to my constructor.
I know if I want do things properly I should use a dependency injection, but I don't really see how to use it here.
How can I simply pass this constructor?
ConsultInvoiceViewModel
private Invoice _selected;
public Invoice Selected
{
get
{
return _selected;
}
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
private void Edit()
{
EditInvoiceViewModel editInvoice = new EditInvoiceViewModel(Selected);
/* doing something here*/
}
public ICommand EditCommand
{
get
{
return editCommand ?? (editCommand = new RelayCommand(p => this.Edit(), p => this.CanEdit()));
}
}
EditInvoiceViewModel
public class EditInvoiceViewModel : ViewModelBase
{
public Context ctx = new Context();
Invoice invoice;
PreInvoice preInvoice;
#region properties
private ObservableCollection<PreInvoice> collection;
public ObservableCollection<PreInvoice> Collection
{
get
{
return collection;
}
set
{
collection = value;
OnPropertyChanged("Collection");
}
}
#endregion
public EditInvoiceViewModel(Invoice inv)
{
/* do stuff*/
}
}
Basically you should avoid passing such parameters into the ViewModels constructor, as wiring it with Inversion of Control/Dependency Injection becomes a pain. While you can use Abstract Factory pattern to resolve objects with runtime parameters, it's imho not suitable for ViewModels.
Instead I always suggest using a form of navigation pattern, similar to how Microsoft's Patterns & Practices team has done with Prism. There you have an INavigationAware interface which your ViewModels can implement. It has 2 methods, NavigateTo and NavigateFrom.
And there is a navigation service. The navigation service will switch the views and before switching calling NavigateFrom in the current ViewModel (if it implements it. One can use it to check if data is saved and if necessary cancel the navigation. After the new View has been loaded and the ViewModel assigned to it, call NavigateTo in the newly navigated ViewModel.
Here you'd pass the parameters required for the ViewModel, in your case invoiceId. Try avoid passing whole models or complex objects. Use the invoiceid to fetch the invoice data and to populate your editing ViewModel.
A basinc implementation from my former answer (can be found here):
public interface INavigationService
{
// T is whatever your base ViewModel class is called
void NavigateTo<T>() where T ViewModel;
void NavigateToNewWindow<T>();
void NavigateToNewWindow<T>(object parameter);
void NavigateTo<T>(object parameter);
}
public class NavigationService : INavigationService
{
private IUnityContainer container;
public NavigationService(IUnityContainer container)
{
this.container = container;
}
public void NavigateToWindow<T>(object parameter) where T : IView
{
// configure your IoC container to resolve a View for a given ViewModel
// i.e. container.Register<IPlotView, PlotWindow>(); in your
// composition root
IView view = container.Resolve<T>();
Window window = view as Window;
if(window!=null)
window.Show();
INavigationAware nav = view as INavigationAware;
if(nav!= null)
nav.NavigatedTo(parameter);
}
}
// IPlotView is an empty interface, only used to be able to resolve
// the PlotWindow w/o needing to reference to it's concrete implementation as
// calling navigationService.NavigateToWindow<PlotWindow>(userId); would violate
// MVVM pattern, where navigationService.NavigateToWindow<IPlotWindow>(userId); doesn't. There are also other ways involving strings or naming
// convention, but this is out of scope for this answer. IView would
// just implement "object DataContext { get; set; }" property, which is already
// implemented Control objects
public class PlotWindow : Window, IView, IPlotView
{
}
public class PlotViewModel : ViewModel, INotifyPropertyChanged, INavigationAware
{
private int plotId;
public void NavigatedTo(object parameter) where T : IView
{
if(!parameter is int)
return; // Wrong parameter type passed
this.plotId = (int)parameter;
Task.Start( () => {
// load the data
PlotData = LoadPlot(plotId);
});
}
private Plot plotData;
public Plot PlotData {
get { return plotData; }
set
{
if(plotData != value)
{
plotData = value;
OnPropertyChanged("PlotData");
}
}
}
}
An example of the INavigationAware interface used in Prism can be found on the projects github repository.
This makes it easy to pass parameter and async load your data (where there isn't any clean way to do this via constructor, as you can't await an async operation inside the constructor without locking, and doing this kind of things in the constructor is very discouraged).
I'm writing a WPF application using MVVM. My ViewModels are quite large and have a lot of logic associated with them (filtering, searching, writing to the database, etc), so I've decided to try to separate out the logic of the ViewModels to a "Presenter" class like is used in MVP.
So, my basic setup is this:
public class FooViewModel : ViewModelBase, IFooViewModel
{
private IFooPresenter presenter;
private ObservableCollection<FooModel> fooCollection;
public FooViewModel()
{
presenter = FooPresenter(this);
}
public ObservableCollection<FooModel> FooCollection
{
get { return fooCollection; }
set
{
fooCollection = value;
OnPropertyChanged("FooCollection");
}
}
public void FooCommandMethod(object obj)
{
presenter.DoStuff();
}
}
public class FooPresenter : IFooPresenter
{
private IFooViewModel viewModel;
public FooPresenter(IFooViewModel viewModel)
{
this.viewModel = viewModel;
}
public void DoStuff()
{
viewModel.FooCollection.Add(new FooModel());
//etc etc, make whatever ViewModel updates are needed
}
}
I feel like it is bad practice to have this circular dependency (View Model depends on Presenter and Presenter depends on View Model). These classes could be combined into one large ViewModel class, but I do like how clean this approach keeps my View Models, all that they do is hold commands that call presenter functions and hold the Model/collections of the Model. I also dislike the dependency of the ViewModel on the concrete implementation of the Presenter. One approach I have toyed with is using a Service Locator type class, so it would look like this:
public FooViewModel()
{
presenter = PresenterLocator.GetPresenter<IFooPresenter>(this);
}
What I would prefer, though, is to use Constructor Dependency Injection to inject the controller when I create the ViewModel. The problem with this is that this creates a circular dependency in the constructors of the ViewModels and Presenters, which causes my application to crash when I attempt to achieve this using Unity. It ends up looking like this:
public FooViewModel(IFooPresenter presenter)
{
this.presenter = presenterl
}
And
public FooPresenter(IFooViewModel viewModel(
{
this.viewModel = viewModel;
}
So, my concern is that my design approach is inherently flawed due to this. Nevertheless, I really like how clean it keeps my ViewModels and separates them from Business Logic. Is there a better way I could be designing this? Is there any way I can use DI to achieve this? Or by doing that am I essentially trying to force a DI container to act as a Service Locator?
First of all, I would not call this a "presenter". This introduces an unwanted confusion, in fact your presenter doesn't present anything, it is just an extracted bit of code from a large view model. Have you considered calling it just "a service"? A SearchService for example?
Another question is: does such service always depend on a view model? Or rather, could it depend on lower layers (unit of works/repos for example) or other services? Note that because your service depends on a view model and you pass a view model directly there, you loose a control of what happens to the view model inside a service. Your DoStuff method is a perfect example, it does something to a view model, alters its state. Instead, you could have
public class FooViewModel : ViewModelBase, IFooViewModel
{
private IFooService service;
private ObservableCollection<FooModel> fooCollection;
public FooViewModel()
{
service = FooService(this);
}
public void FooCommandMethod(object obj)
{
// the responsibility on consuming service outcome is still here!
this.FooCollection.Add( service.CreateNewModel() );
}
}
public class FooService : IFooService
{
// constructor parameter not needed now
public FooService()
{
this.viewModel = viewModel;
}
public FooModel CreateModel()
{
return ...;
}
}
If you still insist however on having a circular dependency, make it so that one of the two has a parameterless constructor and a property injector:
public class FooViewModel : IFooViewModel
{
private IFooService _service;
public FooViewModel( IFooService service )
{
this._service = service;
this._service.Model = this;
}
}
public class FooService : IFooService
{
public IFooViewModel Model { get; set; }
}
This way Unity asked for a IFooViewModel will resolve a parameterless IFooService and then execute the constructor that sets the cycle for both parties.
I'm trying to use Ninject for dependency injection in my MVP application. However, I have a problem because I have two types that depend on each other, thus creating a cyclic dependency. At first, I understand that it was a problem, because I had both types require each other in their constructors. Therefore, I moved one of the dependencies to a property injection instead, but I'm still getting the error message. What am I doing wrong?
This is the presenter:
public class LoginPresenter : Presenter<ILoginView>, ILoginPresenter
{
private ISettings _settings;
private IViewProvider _viewProvider;
private IDataProvider _dataProvider;
public LoginPresenter(
ILoginView view,
ISettings settings,
IViewProvider viewProvider,
IDataProvider dataProvider )
: base( view )
{
_settings = settings;
_viewProvider = viewProvider;
_dataProvider = dataProvider;
}
}
and this is the view:
public partial class LoginForm : Form, ILoginView
{
[Inject]
public ILoginPresenter Presenter { private get; set; }
public LoginForm()
{
InitializeComponent();
}
}
And here's the code that causes the exception:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[MTAThread]
static void Main()
{
// Show the login form
Views.LoginForm loginForm = Kernel.Get<Views.Interfaces.ILoginView>() as Views.LoginForm;
Application.Run( loginForm );
}
}
The exception happens on the line with the Kernel.Get<>() call. Here it is:
Error activating ILoginPresenter using binding from ILoginPresenter to LoginPresenter
A cyclical dependency was detected between the constructors of two services.
Activation path:
4) Injection of dependency ILoginPresenter into property Presenter of type LoginForm
3) Injection of dependency ILoginView into parameter view of constructor of type LoginPresenter
2) Injection of dependency ILoginPresenter into property Presenter of type LoginForm
1) Request for ILoginView
Suggestions:
1) Ensure that you have not declared a dependency for ILoginPresenter on any implementations of the service.
2) Consider combining the services into a single one to remove the cycle.
3) Use property injection instead of constructor injection, and implement IInitializable
if you need initialization logic to be run after property values have been injected.
Why doesn't Ninject understand that since one is constructor injection and the other is property injection, this can work just fine? I even read somewhere looking for the solution to this problem that Ninject supposedly gets this right as long as the cyclic dependency isn't both in the constructors. Apparently not, though. Any help resolving this would be much appreciated.
According to Wikipedia, it's common for the View to manually instantiate its concrete presenter, but I can't do that in my case because as you can see, the presenter has other dependencies that need to be resolved as well.
I got "around" the issue by creating a "PresenterProvider":
public interface IPresenterProvider
{
P Get<P, V>( V view )
where V : IView
where P : IPresenter<V>;
}
public class PresenterProvider : IPresenterProvider
{
private IKernel _kernel;
public PresenterProvider( IKernel kernel )
{
_kernel = kernel;
}
#region IPresenterProvider Members
public P Get<P, V>( V view )
where P : IPresenter<V>
where V : IView
{
return _kernel.Get<P>( new ConstructorArgument( "view", view ) );
}
#endregion
}
Then, in the view I do this:
public partial class LoginForm : Form, ILoginView
{
private ILoginPresenter _presenter;
public LoginForm( IPresenterProvider presenterProvider )
{
InitializeComponent();
_presenter = presenterProvider.Get<ILoginPresenter, ILoginView>( this );
}
}
The presenter stays the same. This way, I'm "solving" the cyclic dependency manually. Better suggestions are still welcome, of course.
using MVP, what is the normal order of construction and dependency injection.
normally you create a presenter for each view and pass the view into the presenter on constructor. But what if you have:
A Service that multiple views need to listen to events on.
Multiple views all pointing to the same data model cache.
can someone display a normal flow of info from a user click to data coming back in a service from a server.
Here is what I do:
First, I define theses interfaces:
public interface IView<TPresenter>
{
TPresenter Presenter { get; set; }
}
public interface IPresenter<TView, TPresenter>
where TView : IView<TPresenter>
where TPresenter : IPresenter<TView, TPresenter>
{
TView View { get; set; }
}
Then this abstract presenter class:
public abstract class AbstractPresenter<TView, TPresenter> : IPresenter<TView, TPresenter>
where TView : IView<TPresenter>
where TPresenter : class, IPresenter<TView, TPresenter>
{
protected TView view;
public TView View
{
get { return this.view; }
set
{
this.view = value;
this.view.Presenter = this as TPresenter;
}
}
}
The view is injected via a property, instead of the constructor, to allow the bi-directional affection in the setter. Notice that a safe cast is needed...
Then, my concrete presenter is something like :
public class MyPresenter : AbstractPresenter<IMyView, MyPresenter>
{
//...
}
Where IMyView implements IView. A concrete view type must exists (e.g. MyView), but it's the container that resolves it:
I register MyPresenter type as itself in the container, with a transient behavior.
I register MyView as an IMyView in the container with a transient behavior.
I then asks for a MyPresenter to the container.
Container instanciate a MyView
It instanciates a MyPresenter
It inject the view into the presenter through the AbstractPresenter.View property.
The setter code completes the bi-directional association
The container returns the couple Presenter/View
It allows you to inject other dependencies (services, repos) into both your view and your presenter. But in the scenario you described, I recommend you to inject services and caches into the presenter, instead of the view.
In WinForms, I prefer a simple approach. Usually you're dealing with a few UserControls on a design surface -- make these your view classes. .NET creates the control hierarchy for you (via InitializeComponent). If you use the Passive View pattern, each view then instantiates it's presenter. (You can do this either directly or by asking an IOC container.) Use constructor injection to pass a reference to the view's interface to the presenter's constructor. The presenter can then wire itself up to view events. Repeat the process for the model: the presenter instantiates a model and wires up to its events. (In this case you don't need the constructor injection since Passive View says the presenter keeps a reference to the model, not vice versa.)
The only nit I've found with this approach is properly managing lifetimes of the model and presenter. You want to keep the view as simple as possible, so you probably don't want it maintaining a reference to the presenter. However, that means you've got this presenter object hanging around with event handlers tied to your view. This setup prevents your view from being garbage collected. One solution is to have your view publish an event that indicates it's closing. The presenter would receive the event and remove both its model and view subscriptions. The objects in your web are now properly dereferenced and the garbage collector can go about its work.
You wind up with something like the following:
public interface IView
{
...
event Action SomeEvent;
event EventHandler Disposed;
...
}
// Note that the IView.Disposed event is implemented by the
// UserControl.Disposed event.
public class View : UserControl, IView
{
public event Action SomeEvent;
public View()
{
var presenter = new Presenter(this);
}
}
public interface IModel
{
...
event Action ModelChanged;
...
}
public class Model : IModel
{
...
public event Action ModelChanged;
...
}
public class Presenter
{
private IView MyView;
private IModel MyModel;
public Presenter(View view)
{
MyView = view;
MyView.SomeEvent += RespondToSomeEvent;
MyView.Disposed += ViewDisposed;
MyModel = new Model();
MyModel.ModelChanged += RespondToModelChanged;
}
// You could take this a step further by implementing IDisposable on the
// presenter and having View.Dispose() trigger Presenter.Dispose().
private void ViewDisposed(object sender, EventArgs e)
{
MyView.SomeEvent -= RespondToSomeEvent;
MyView.Disposed -= ViewDisposed;
MyView = null;
MyModel.Modelchanged -= RespondToModelChanged;
MyModel = null;
}
}
You can decouple this example a step further by using IOC and asking your IOC container for implementations of IModel (in the Presenter class) and IPresenter (in the View class).
interface IEmployee
{
int EmployeeId {get;}
string FirstName {get;}
string LastName {get;}
}
interface IEmployeeRepository
{
void SaveEmployee(IEmployee employee);
IEmployee GetEmployeeById(int employeeId);
IEmployee[] Employees { get; }
}
interface IEmployeeView
{
event Action<IEmployee> OnEmployeeSaved;
}
interface IEmployeeController
{
IEmployeeView View {get;}
IEmployeeRepository Repository {get;}
IEmployee[] Employees {get;}
}
partial class EmployeeView: UserControl, IEmployeeView
{
public EmployeeView()
{
InitComponent();
}
}
class EmployeeController:IEmployeeController
{
private IEmployeeView view;
private IEmployeeRepository repository;
public EmployeeController(IEmployeeView view, IEmployeeRepository repository)
{
this.repository = repository;
this.view = view;
this.view.OnEmployeeSaved+=new Action<IEmployee>(view_OnEmployeeSaved);
}
void view_OnEmployeeSaved(IEmployee employee)
{
repository.SaveEmployee(employee);
}
public IEmployeeView View
{
get
{
return view;
}
}
public IEmployeeRepository Repository
{
get
{
return repository;
}
}
public IEmployee[] Employees
{
get
{
return repository.Employees;
}
}
}
WinformsMVP is a very good MVP framework for Windows forms. You can easily inject an service across multiple views easily using this framework. This is a good article with a sample source code explains how to use the framework.