Solving a cyclical dependency in Ninject (Compact Framework) - c#

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.

Related

How to fix a Circular Dependency

So I've just recently started using the Microsoft.Extensions.DependencyInjection nuget package in my WPF project because I wanted to start learning more about DI.
Issue
I keep getting a Circular Dependency Exception whenever I try to access a dependency from any other ViewModel besides the MainViewModel
This is what I have done so far.
I've installed these two Nuget packages into my project
Microsoft.Extensions.Hosting --version 7.0.0
Microsoft.Extensions.DependencyInjection --version 7.0.0
And then I went ahead and created my container inside my App.xaml.cs
public partial class App : Application
{
private readonly ServiceProvider _serviceProvider;
public App()
{
IServiceCollection _services = new ServiceCollection();
_services.AddSingleton<MainViewModel>();
_services.AddSingleton<HomeViewModel>();
_services.AddSingleton<SettingsViewModel>();
_services.AddSingleton<DataService>();
_services.AddSingleton<NavService>();
_services.AddSingleton<MainWindow>(o => new MainWindow
{
DataContext = o.GetRequiredService<MainViewModel>()
});
_serviceProvider = _services.BuildServiceProvider();
}
protected override void OnStartup(StartupEventArgs e)
{
var MainWindow = _serviceProvider.GetRequiredService<MainWindow>();
MainWindow.Show();
base.OnStartup(e);
}
}
In my App.xaml I also defined a few DataTemplates which will allow me to display different views based in their DataType
<Application.Resources>
<DataTemplate DataType="{x:Type viewModel:HomeViewModel}">
<view:HomeView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:SettingsViewModel}">
<view:SettingsView/>
</DataTemplate>
</Application.Resources>
Then I went ahead and created my MainWindow.xaml
<Window x:Class="Navs.MainWindow"
...>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border>
<StackPanel>
<Button Height="25" Content="Home" Command="{Binding HomeViewCommand}"/>
<Button Height="25" Content="Settings" Command="{Binding SettingsViewCommand}"/>
</StackPanel>
</Border>
<ContentControl Grid.Column="1" Content="{Binding NavService.CurrentView}">
</ContentControl>
</Grid>
</Window>
And a corresponding ViewModel
public class MainViewModel : ObservableObject
{
private NavService _navService;
public NavService NavService
{
get => _navService;
set
{
_navService = value;
OnPropertyChanged();
}
}
/* Commands */
public RelayCommand SettingsViewCommand { get; set; }
public RelayCommand HomeViewCommand { get; set; }
public MainViewModel(NavService navService, HomeViewModel homeViewModel, SettingsViewModel settingsViewModel)
{
NavService = navService;
HomeViewCommand = new RelayCommand(o => true, o => { NavService.CurrentView = homeViewModel; });
SettingsViewCommand = new RelayCommand(o => true, o => { NavService.CurrentView = settingsViewModel; });
}
}
As you can see, with the help of Dependency Injection, I can now access the objects I've registered in my container through the constructor.
I've also created two UserControls
UserControl1
<Grid>
<StackPanel VerticalAlignment="Center">
<Button Height="25" Content="Click me" Command="{Binding OpenWindowCommand}" />
<Button Content="Settings View" Command="{Binding SettingsViewCommand}" Height="25" />
</StackPanel>
</Grid>
And it's corresponding ViewModel
public class HomeViewModel
{
public RelayCommand SettingsViewCommand { get; set; }
public HomeViewModel()
{
}
}
And then we have UserControl2
<Grid>
<StackPanel VerticalAlignment="Center">
<TextBox Text="{Binding Message}"
Height="25"/>
<Button Height="25" Content="Home View" Command="{Binding HomeViewCommand}"/>
<Button Height="25" Content="Fetch" Command="{Binding FetchDataCommand}"/>
</StackPanel>
</Grid>
With it's corresponding ViewModel
public class SettingsViewModel : ObservableObject
{
public string Message { get; set; }
public RelayCommand HomeViewCommand { get; set; }
public RelayCommand FetchDataCommand { get; set; }
public SettingsViewModel()
{
}
}
The NavService.cs
public class NavService : ObservableObject
{
private object _currentView;
public object CurrentView
{
get => _currentView;
set
{
_currentView = value;
OnPropertyChanged();
}
}
private HomeViewModel HomeViewModel { get; set; }
private SettingsViewModel SettingsViewModel { get; set; }
public NavService(HomeViewModel homeViewModel, SettingsViewModel settingsViewModel)
{
HomeViewModel = homeViewModel;
SettingsViewModel = settingsViewModel;
CurrentView = HomeViewModel;
}
public void NavigateTo(string viewName)
{
switch (viewName)
{
case "Settings":
CurrentView = SettingsViewModel;
break;
case "Home":
CurrentView = HomeViewModel;
break;
}
}
}
This all works just fine, the issue occurs when I take the HomeViewModel and try to pass in the NavService as a constructor.
public HomeViewModel(NavService navService)
{
}
At that point, it throws the exception.
I want to be able to access the NavService from various Views so that I can change the NavService.CurrentView from multiple places.
This is a design issue. The main view model tightly coupled, is acting as a pass through and violating SRP (Single responsibility principle). The navigation service and other view models both explicitly depend on each other, which is the direct cause of the circular dependency issue.
For simplicity, note the following refactor for the NavService
public abstract class ViewModel : ObservableObject {
}
public interface INavigationService {
object CurrentView { get; }
void NavigateTo<T>() where T : ViewModel;
}
public class NavService : INavigationService, ObservableObject {
private readonly Func<Type, object> factory;
private object _currentView;
public NavService(Func<Type, object> factory) {
this.factory = factory;
}
public object CurrentView {
get => _currentView;
private set {
_currentView = value;
OnPropertyChanged();
}
}
public void NavigateTo<T>() where T: ViewModel {
object viewModel = factory.Invoke(typeof(T))
?? throw new InvalidOperationException("Error message here");
CurrentView = viewModel;
}
}
This service when registered should configure the factory used to get the view models.
public partial class App : Application {
private readonly IServiceProvider _serviceProvider;
public App() {
IServiceCollection _services = new ServiceCollection();
_services.AddSingleton<MainViewModel>();
_services.AddSingleton<HomeViewModel>();
_services.AddSingleton<SettingsViewModel>();
_services.AddSingleton<DataService>();
_services.AddSingleton<INavigationService, NavService>()(sp => {
return new NavService(type => sp.GetRequiredService(type));
});
_services.AddSingleton<MainWindow>(o => new MainWindow {
DataContext = o.GetRequiredService<MainViewModel>()
});
_serviceProvider = _services.BuildServiceProvider();
}
protected override void OnStartup(StartupEventArgs e) {
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
base.OnStartup(e);
}
}
This completely decouples the main and other view models but allows for strongly typed navigation and removes the circular dependency since in this particular scenario the models only need know about the navigation service
public class MainViewModel : ViewModel {
private INavigationService _navService;
/* Ctor */
public MainViewModel(INavigationService navService) {
NavService = navService;
HomeViewCommand = new RelayCommand(o => true, o => { NavService.NavigateTo<HomeViewModel>(); });
SettingsViewCommand = new RelayCommand(o => true, o => { NavService.NavigateTo<SettingsViewModel(); });
}
public INavigationService NavService {
get => _navService;
set {
_navService = value;
OnPropertyChanged();
}
}
/* Commands */
public RelayCommand SettingsViewCommand { get; set; }
public RelayCommand HomeViewCommand { get; set; }
}
Note that no changes were needed in the views. The navigation service is also now flexible enough to allow any number of view models to be introduced into the system with no changes needed to be made to it.
It's rarely a good idea to resolve mainwindow out your DI container.
You want that rendered ASAP and what are you going to inject into it's constructor?
Probably nothing.
What are you going to switch it out for?
Probably nothing.
The main practical reason you want interfaces is so you can mock that class in your unit tests.
Everything you build should have a single responsibility.
The mainwindow's job is to contain what you initially show the user. Maybe pretty much everything.
Unit testing UI is quite a challenge so it's common to reduce what goes into it to re-usable components and not write tests.
You should not pass in the concrete versions of viewmodels to mainviewmodel. If it needs to know about them, what do you do when you have 50 views?
public MainViewModel(NavService navService)
{
Navservice should resolve concrete instances on demand. More like.
NavService.CurrentView =
(IInitiatedViewModel)serviceProvider.GetService(typeofregisteredinterface);
The serviceprovider is an instance class. You need some sort of reference to it unless you instantiate absolutely everything in app.xaml.cs resolving everything at start up.
In a real world application, you will need transients. You will not be able to rely on everything being a singleton.
You will want to navigate to a NEW instance of a FooViewModel because you want a new Foo which isn't the same as the last Foo and will not be the same as a future Foo. You will want a new Customer or repository instance.
You will have more complicated things in any real app than two viewmodels.
Note that serviceprovider is:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.serviceprovider?view=dotnet-plat-ext-7.0
Which already has an interface defined IServiceProvider. So you could easily inject a mock for testing purposes.
The serviceprovider you use in app.xaml will need to be referenced somehow.
You usually want the viewmodel interface:
interface IInitiatedViewModel
{
Task Initiate();
}
So you can get any data for your viewmodel after it's instantiated.
public async Task Initiate()
{
Suppliers = await _repository.GetAddressesByTypeAsync((int)AddressType.Supplier);
if(Suppliers.Count == 1)
{
ChosenSupplier = Suppliers[0];
}
}
I suggest you should also have a list somewhere which has Type and Description of your viewmodel and view.
You can then abstract away navigation from specific viewmodel types.
They're choosing whatever the [3] view is and that is called whatever is in description, it's viewmodel interface is whatever is in Type.
If necessary you can then extend this principle to have an optional factory method in there.
And logic can be in your navigation service or another injected class.
Parent viewmodels such as homeviewmodel may have dependencies but they use things rather than get used by something else. There is no real advantage to defining an interface for them because you never really replace them with a moq for tests. That means there's no need to register an interface as being associated with them.
I often find there are a lot of these.
You can define some custom attributes for these and compose your navigation list dynamically. This saves editing separate things.
You don't want to compose this list before you've shown the user the first view so it's usual to resolve HomeViewModel and MainWindowViewModel immediately. You can register these close to your entry point for di if necessary.
Others can be added using reflection.
Hence you could have viewmodels decorated:
[ParentViewModel("Foo View Name Here")]
....
public class FooViewModel()
{
You can find code samples which allow such reflection:
How enumerate all classes with custom class attribute?
As your app grows you might have many views. Iterating all those classes can be done in a console app generates xml or a source generator. You can also have attributes define aspects such as menu location. Because attributes go on classes, they're associated with the code you're writing/maintaining rather than completely disconnected. That means you're less likely to make mistakes like mis spell an enum or fail to remove an obsolete enum entry when you remove an unwanted view.
Attribute driven generation is very powerful.
You could use code generation to generate interfaces and registration for repeated patterns such as views and viewmodels.
You might not find any value in explicitly registering these with the dependency injection container if you do not want a singleton for each.
You can instantiate an instance of an UnregisteredClass using ActivatorUtilities.CreateInstance
ActivatorUtilities.CreateInstance<UnregisteredClass>(serviceProvider);
That will provide any dependencies to your UnregisteredClass.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createinstance?view=dotnet-plat-ext-7.0&viewFallbackFrom=aspnetcore-2.1#Microsoft_Extensions_DependencyInjection_ActivatorUtilities_CreateInstance__1_System_IServiceProvider_System_Object___
There's an optional parameter which can be useful to provide variable parameters. Like say you want Invoice nnn.
Don't configure the IoC container in the constructor! Move related code to your OnStartup override or the Application.Startup event handler. The constructor is only meant to initialize/configure the instance. The constructor must always return fast.
Your are implementing Dependency Injection wrong. As you have currently implemented it, it defies its purpose. First step is always to follow the Dependency Inversion principle (the D in SOLID): don't depend on concrete types. Rather depend on their abstractions.
This means you have to introduce abstract classes and interfaces. Then only inject those abstractions into your concrete types.
Circular dependencies are usually introduced by designing wrong responsibilities (bad class design). IoC reveals this design flaw because dependencies are now publicly exposed, usually via the constructor.
Circular dependencies exist on constructor level and on class level.
A constructor level and class level circular dependency exist independent of each other and must be fixed separately. Fixing one doesn't fix the other. It's the constructor level circular dependency that throws the InvalidOperationException or StackOverflowException.
From a class level design perspective,
when type A depends on B and B on A (A ⟷ B)
then you have a circular dependency and the following options to fix it:
a) A and Bshould be merged into a single class (A)
b) B has too much responsibility or too much knowledge of A or other classes in general. Move related responsibility back to A. Now B would have to use A to fulfill its responsibility
A ⟷ B ➽ A ⟶ B
c) the shared logic must be moved/extracted to a third type C:
A ⟷ B ➽ A ⟶ C ⟵ B
d) introduce interfaces to invert the dependency (Dependency Inversion principle):
IA
⬀ ⬉
A ⟷ B ➽ A B
⬊ ⬃
IB
This means:
a) A knows how to navigate. This could lead to A having too much responsibility. The proof: every type that needs to navigate also has to implement the complete logic (duplicate code)
b) every type knows where it can/is allowed to navigate to. While the navigation logic is encapsulated by a dedicated type (NavigationService), the actual valid destination is only known to the client. This adds robustness to the code. In you case, this would mean A will have to provide B with arguments to allow B to fulfill its responsibility. B is now unaware of the existence of A (A ➞ B).
c) because the dependency is not introduced to make particular class members (API) available, c) can't be applied in your case. In your case your B depends on A as a type alone (instance and not instance members).
d) because the circular dependency is manifested in the constructor, introducing interfaces alone won't resolve the circular dependency exception thrown by the IoC container (or creator in general).
Three Solutions
To fix your original problem you have three options:
hide the (constructor) dependencies behind a factory (not recommended)
fix your design. The NavigationService knows too much. Following your pattern, NavigationService will have to know every view model class (or every navigation destination) explicitly.
use property injection instead of constructor injection (not recommended)
The following examples will use a Func<TProduct> instead of an abstract factory to simplify the examples.
The examples also use an enum as destination identifier to eliminate the use of magic strings
and assume that you have introduced an interface for each dependency.
It's important to understand that there are basically two circular dependencies: class level and constructor. Both can be resolved individually.
The class level circular dependency is usually resolved by introducing interfaces (applying the Dependency Inversion principle).
The constructor circular dependency is fixed using one of the three below suggestions.
For the sake of completeness, all three suggestions also fix the class level circular dependency (although it is not responsible for the circular dependency exception thrown by the IoC container).
NavigationId.cs
enum which is used by all examples to replace the magic string parameter to identify the navigation destination.
public enum NavigationId
{
None = 0,
HomeScreen,
SettingsScreen
}
Solution 1): Hide dependencies (not recommended)
Instead of depending on explicit types, let your classes depend on (abstract) factories by implementing the Abstract Factory pattern.
Note, there still will be an implicit circular dependency. It is just hidden behind factories. The dependency is just removed from the constructor (constructor dependency - constructing a NavigationService no longer requires the construction of HomeViewModel and vice versa).
As already mentioned, you would have to introduce interfaces (for example a IHomeViewModel) to completely remove the circular dependency.
You will also see that in order to add more destinations you would have to modify the NavigationService too. This is a good indicator that you have implemented a bad design. In fact, you have violated the Open-Closed principle (the O in SOLID).
NavigationService.cs
class NavigationService : INavigationService, INotifyPropertyChanged
{
// Constructor.
// Because of the factory the circular dependency of the constructor
// is broken. On class level the dependency still exists,
// but could be removed by introducing a 'IHomeViewModel' interface.
public NavigationService(Func<IHomeViewModel> homeViewModelFactory)
{
// This reveals that the class knows too much.
// To introduce more destinations,
// you will always have to modify this code.
// Same applies to your switch-statement.
// A switch-statement is another good indicator
// for breaking the Open-Closed principle
this.NavigationDestinationFactoryTable = new Dictionary<NavigationId, Func<object>>()
{
{ NavigationId.HomeScreen, homeViewModelFactory.Invoke()}
};
}
public void Navigate(NavigationId navigationId)
=> this.CurrentSource = this.NavigationDestinationTable.TryGetValue(navigationId, out Func<object> factory) ? factory.Invoke() : default;
public object CurrentSource { get; private set; }
private Dictionary<NavigationId, Func<object>> NavigationDestinationFactoryTable { get; }
}
HomeViewModel.cs
class HomeViewModel : IHomeViewModel, INotifyPropertyChanged
{
private INavigationService NavigationService { get; }
// Constructor
public HomeViewModel(Func<INavigationService> navigationServiceFactory)
=> this.NavigationService = navigationServiceFactory.Invoke();
}
App.xaml.cs
Configure the IoC container to inject the factories. In this example the factories are simple Func<T> delegates. For more complex scenarios you probably want to implement abstract factories instead.
protected override void OnStartup(StartupEventArgs e)
{
IServiceCollection _services = new ServiceCollection();
// Because ServiceCollection registration members return the current ServiceCollection instance
// you can chain registrations
_services.AddSingleton<IHomeViewModel, HomeViewModel>()
.AddSingleton<INavigationService, NavigationService>()
/* Register the factory delegates */
.AddSingleton<Func<IHomeViewModel>>(serviceProvider => serviceProvider.GetRequiredService<HomeViewModel>)
.AddSingleton<Func<INavigationService>>(serviceProvider => serviceProvider.GetRequiredService<NavigationService>);
}
Solution 2): Fix the class design/responsibilities (recommended)
Every class should know the navigation destinations it is allowed to navigate to. No class should know about an other class where it can navigate to or if it can navigate at all.
Opposed to solution 1), the circular dependency is completely lifted.
NavigationService.cs
public class NavigationService : INavigationService, INotifyPropertyChanged
{
// The critical knowledge of particular types is now removed
public NavigationService()
{}
// Every class that wants to navigate to a destination
// must know/provide his destination explicitly
public void Navigate(object navigationDestination)
=> this.CurrentSource = navigationDestination;
public object CurrentSource { get; private set; }
}
HomeViewModel.cs
class HomeViewModel : IHomeViewModel, INotifyPropertyChanged
{
private INavigationService NavigationService { get; }
// Constructor
public HomeViewModel(INavigationService navigationService)
=> this.NavigationService = navigationService;
}
Solution 3): Property injection
Property injection is not supported by the .NET dependency injection framework. However, property injection is generally not recommended. Aside from hiding dependencies, it imposes the danger of accidentally making a bad class design work instead of fixing what really needed to be fixed (as it would be the case with this example).
While 2) is the recommended solution, you can combine both solutions 1) and 2) and decide how much the particular navigation source needs to know about destinations.
public class NavigationService : INavigationService, INotifyPropertyChanged
{
public Navigator(Func<IHomeViewModel> homeViewModelFactory)
{
this.HomeViewModelFactory = homeViewModelFactory;
// This reveals that the class knows too much.
// To introduce more destinations,
// you will always have to modify this code.
// Same applies to your switch-statement.
// A switch-statement is another good indicator
// for breaking the Open-Closed principle
this.NavigationDestinationFactoryTable = new Dictionary<NavigationId, Func<object>>()
{
{ NavigationId.HomeScreen, homeViewModelFactory }
};
}
public void Navigate(NavigationId navigationId)
=> this.CurrentSource = this.NavigationDestinationTable.TryGetValue(navigationId, out Func<object> factory) ? factory.Invoke() : default;
public void Navigate(object navigationDestination)
=> this.CurrentSource = navigationDestination;
public object CurrentSource { get; private set; }
public Func<IHomeViewModel> HomeViewModelFactory { get; }
private Dictionary<NavigationId, Func<object>> NavigationDestinationFactoryTable { get; }
}
Then improve the MainViewModel initialization and clean up its dependencies.
It should use the NavigationService instead of explicit assignment.
That's why it got an NavigationService injected:
MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
// Must be read-only
public INavigationService NavigationService { get; }
/* Commands. Must be read-only too */
public RelayCommand SettingsViewCommand { get; }
public RelayCommand HomeViewCommand { get; }
public MainViewModel(INavigationService navigationService)
{
this.NavigationService = navigationService;
this.HomeViewCommand = new RelayCommand(
o => true,
o => this.NavigationService.Navigate(NavigationId.HomeScreen));
this.SettingsViewCommand = new RelayCommand(
o => true,
o => this.NavigationService.Navigate(NavigationId.SettingsScreen));
}
}

Winforms IoC Container - How to handle concrete types with a presenter factory

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.

Is this design pattern code smell? How to achieve this using DI?

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.

Using property injection instead of constructor injection

Long story short, I'm trying to use ELMAH with MVC 2 and Ninject, and I need to use parameterless constructors. I created an initial post about it here: Using a parameterless controller constructor with Ninject?
I was advised to use property injection instead of constructor injection. So I moved from this:
public class DepartmentsController : Controller
{
private IDepartmentsRepository departmentsRepository;
public DepartmentsController(IDepartmentsRepository departmentsRepository)
{
this.departmentsRepository = departmentsRepository;
}
...
}
to this:
public class DepartmentsController : Controller
{
private IDepartmentsRepository _departmentsRepository;
[Inject]
public IDepartmentsRepository DepartmentsRepository
{
get { return _departmentsRepository; }
set { _departmentsRepository = value; }
}
...
}
But in my other controller functions, whether I try to access DepartmentsRepository or _departmentsRepository, I get an object reference not set to an instance of an object error when I try to access it.
Is there something else I need to do here?
I had a similar problem. Have a look at my questions: Using Ninject with Membership.Provider.
Basically when you initialise DepartmentsController you need to injectthis (i.e. your departments controller into your Ninject kernal. So its something like:
public class DepartmentsController : Controller
{
private IDepartmentsRepository _departmentsRepository;
[Inject]
public IDepartmentsRepository DepartmentsRepository
{
get { return _departmentsRepository; }
set { _departmentsRepository = value; }
}
public DepartmentsController()
{
NinjectHelper.Kernel.Inject(this);
}
}
Where NinjectHelper in this case gets the current Ninject Kernel.
Try something like this:
Global.asax.cs
protected void Application_Start()
{
DependencyResolver.SetResolver(
new MyDependencyResolver(
new StandardKernel(
new MyModule())));
//...
}
MyDependencyResolver.cs
public class MyDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public MyDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
}
MyModule.cs
public class MyModule : NinjectModule
{
public override void Load()
{
Bind<IDepartmentsRepository>().To<DepartmentsRepository>();
}
}
There could be 2 reasons for object reference not set exception.
1) Ninject does not know how to Bind IDepartmentsRepository to a concrete implementation of DepartmentsRepository ( I doubt that is the case though )
2) If you are trying to access DepartmentsRepository property in your controller's constructor, it will throw the exception (since Ninject is only able to inject Property Dependencies after the object is constructed).
Hope that helps.
As Daniel T. in the above comment posted, you should check out Ninject.Web.Mvc. If you use the NinjectHttpApplication in that project, it will autowire everything for you, so that when the NinjectControllerFactory constructs a new controller, it will call Inject() for you to fill the property injections.
An observation for anyone arriving here having problems "Using property injection instead of constructor injection" with Ninject even if not specifically with MVC Controllers.
Ninject will only identify the [Inject] attribute on a property and perform the property injection on classes that are being brought to life as part of a Ninject chain of DI.
If you are creating the object like this
var myObj = new MyObj();
Ninject doesn't know about the class instantiation and so won't know to perform any injection.
In the MVC world you can use
var emailer = DependencyResolver.Current.GetService<IEmailer>();

How to Inject daoFactory into NHibernate EventListener

I need to Inject some global service (daoFactory) into EventListenet subscribed on PostUpdate event. I`ve read that it is possible to do this way:
public class YourPostInsertListener : IPostInsertEventListener
{
private readonly IPersistentAuditor auditor;
public YourPostInsertListener(IPersistentAuditor auditor)
{
this.auditor = auditor;
}
public void OnPostInsert(PostInsertEvent #event)
But this code just throws exception: no parameterless constructor was specified for EventListener. And this is understandable behavior, because I haven`t added my service to any container. So how can I specify the IoC contauner in NHibernate?
The IoC that I've been using is Ninject. The best way I found so far is to take advantage of the ServiceLocator provdided by the Microsoft Patterns and Practices guys:
internal class YourPostInsertListener : IPostInsertEventListener
{
IKernel Kernel
{
get
{
return ServiceLocator.Current.GetInstance<IKernel>();
}
}
IPersistentAuditor
{
get
{
return Kernel.Get<IPersistentAuditor>();
}
}
// ... Rest of class
}
In the class that sets up your IoC container you would do this:
ServiceLocator.SetLocatorProvider( () => new NinjectServiceLocator( kernel ) );

Categories

Resources