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));
}
}
Related
In the project I'm working on, I've added a base ViewModel class which contains some functionality and dependencies common to all ViewModels. It provides validation, messaging, dispatching and navigation services through the following properties:
IValidateProperties Validator { get; }
IMessenger Messenger { get; }
IDispatcherHelper DispatcherHelper { get; }
INavigationService Navigation { get; }
I use an IoC container to wire my dependencies, however I have a few options for how to handle these dependencies which are common to all of my ViewModels:
Inject them in the constructor. If I did this, then it would require adding these four arguments to the constructor of every single ViewModel and pass them to the base constructor. That's a lot of extra noise added to my code base, which I'd really rather avoid. Also, if I were to add another dependency at some point, that would require changing the constructor of every single ViewModel.
Use property injection. This is the approach I'm working with now. Unfortunately, it means not being able to access these properties until after the ViewModel has been constructed, resulting in the following workarounds:
private IValidateProperties _validator;
public IValidateProperties Validator
{
get => _validator;
set
{
_validator = value;
_validator.ValidationTarget = this;
}
}
private IMessenger _messenger;
public IMessenger Messenger
{
get => _messenger;
set
{
_messenger = value;
MessengerAttached();
}
}
protected virtual void MessengerAttached() { }
Make the properties static and inject them on app startup. This is easy for Messenger, DispatcherHelper and Navigation because they are used as singletons anyway. For Validator, I would need to add a static ValidatorFactory, and instantiate the Validator in the constructor using the factory. This way seems to be the cleanest way to do things, but I have this voice in the back of my head telling me that using statics like this is a bad idea.
I feel like option 1 is out of the question because of the large amount of noisy boilerplate code it would result in being added to my ViewModels. I'm still unsure whether 2 or 3 is the best way to go though. Is there a good reason that using statics is a bad idea in this case, or am I fretting over nothing?
Some people argue that statics lead to untestable code, but in this case it would actually make things easier to test. If I were to go with option 3, I could add the following class for all of my view model tests to inherit:
public abstract class ViewModelTestBase
{
protected readonly IValidateProperties ValidatorMock;
protected readonly IMessenger MessengerMock;
protected readonly IDispatcherHelper DispatcherHelperMock;
protected readonly INavigationService NavigationMock;
protected ViewModelTestBase()
{
ValidatorMock = Substitute.For<IValidateProperties>();
ViewModelBase.Validator = ValidatorMock;
MessengerMock = Substitute.For<IMessenger>();
ViewModelBase.Messenger = MessengerMock;
DispatcherHelperMock = Substitute.For<IDispatcherHelper>();
ViewModelBase.DispatcherHelper = DispatcherHelperMock;
NavigationMock = Substitute.For<INavigationService>();
ViewModelBase.Navigation = NavigationMock;
}
}
So, what concrete reasons are there for not going with approach #3? And if statics really are such a bad idea in this case, what concrete reasons are there for not going with approach #2 instead?
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.
These days I'm facing this situation often and I'm looking for an elegant solution. I have :
public abstract class TypeA
{
public abstract void AbtractMethod(IDependency dependency);
}
public class TypeB : TypeA
{
public override void AbtractMethod(ISpecializedDependencyForB dependency) { }
}
public class TypeC : TypeA
{
public override void AbtractMethod(ISpecializedDependencyForC dependency) { }
}
public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }
My objective is to make things transparent in the client perspective and to consume this code like that :
TypeA myDomainObject = database.TypeARepository.GetById(id); // The important point here is that I don't know if the object is of TypeB or TypeC when I consume it.
IDependency dependency = ? // How do I get the right dependency
myDomainObject.AbtractMethod(dependency);
So the thing is that since I don't know the concrete type of the object, I can't inject the right dependency into it.
What I'm currently doing is that I create an abstract factory, to inject the right properties. I have two problems with that, the first one is that I would end up with a lot of factories. The second one is that it makes polymorphism useless since the client actually needs to care about "managing" the underlying type (I need to inject all the possible dependencies in the factory, and to instantiate the factory on the client code).
1) Therefore I was thinking of using property injection with unity, but I can't find out if it's possible to resolve the dependencies of an object, after it's been instanciated manually. Even with this approach I think I could still meet the same problem : I'm not sure if unity would check the actual type of the object and resolve the right dependency if a syntax like this existed :
unityContainer.Resolve<TypeA>(myDomainObject)
If not, I would need to know the type in advance and would be back to the same problem.
2) I have found this article mentionning that EF provides some mechanism for DI, but it seems that it is only meant to inject the framework services (PluralizationService, etc...). Otherwise it would have been a nice way to achieve that.
3) I could also not use DI in this case... It looks like by concept DI does not fit well with polymorphism. I'm not excited by this idea though.
I'd be happy to have a solution for the property injection I'm trying to achieve, or an idea of pattern I could use. However I really don't want to create a big infrastructure and obfuscate my code just for this purpose.
Note : I don't want to you use domain events in this case.
Thank you
TL;DR
Replace the IDependency parameter of the polymorphic AbstractMethod with an implementation-specific construction dependency parameter, which is injected by the IoC container, not by the consumer.
In more detail
The original class hierarchy will need to look like more like this for inheritance polymorphicism to work, as the superclass virtual method and subclass override methods must match signatures:
public abstract class TypeA // superclass
{
public abstract void AbtractMethod(IDependency dependency);
}
public class TypeB : TypeA // subclass 1
{
public override void AbtractMethod(IDependency dependency)
{
Contract.Requires(dependency is ISpecializedDependencyForB);
// ...
}
}
public class TypeC : TypeA // subclass 2
{
public override void AbtractMethod(IDependency dependency)
{
Contract.Requires(dependency is ISpecializedDependencyForC)
// ...
}
}
However, some things don't ring true with this design:
The LSP appears to be violated, since the although AbtractMethod() advertises that it accepts the base IDependency interface, the two subclasses actually depend on a specialized subclassed dependency.
It is also unusual, and arguably inconvenient, for a caller of these methods to build up the correct dependency and pass it to the method in order for it to be invoked correctly.
So, if possible, I would adopt a more conventional approach to the arrangement of dependencies, whereby the dependency is passed to the subclass constructor, and will be available to the polymorphic method when needed. This decouples the need to supply the appropriate IDependency to the method. Leave it to the IoC container to do the appropriate dependency resolution:
Use constructor injection to create the correct dependency into Classes TypeB and TypeC
If there is a secondary requirement to Expose an IDependency on the base class TypeA to consumers, then add an additional abstract property to TypeA of type IDependency (but this seems iffy)
As per Ewan's observation, the repository would need some kind of strategy pattern in order to serve up polymorphic domain entities (B or C). In which case, couple the repository to a factory to do exactly this. The concrete factory would need to be bound to the container in order to tap into Resolve().
So putting this all together, you might wind up with something like this:
using System;
using System.Diagnostics;
using Microsoft.Practices.Unity;
namespace SO29233419
{
public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }
public class ConcreteDependencyForB : ISpecializedDependencyForB {};
public class ConcreteDependencyForC : ISpecializedDependencyForC { };
public abstract class TypeA
{
// Your polymorphic method
public abstract void AbtractMethod();
// Only exposing this for the purpose of demonstration
public abstract IDependency Dependency { get; }
}
public class TypeB : TypeA
{
private readonly ISpecializedDependencyForB _dependency;
public TypeB(ISpecializedDependencyForB dependency)
{
_dependency = dependency;
}
public override void AbtractMethod()
{
// Do stuff with ISpecializedDependencyForB without leaking the dependency to the caller
}
// You hopefully won't need this prop
public override IDependency Dependency
{
get { return _dependency; }
}
}
public class TypeC : TypeA
{
private readonly ISpecializedDependencyForC _dependency;
public TypeC(ISpecializedDependencyForC dependency)
{
_dependency = dependency;
}
public override void AbtractMethod()
{
// Do stuff with ISpecializedDependencyForC without leaking the dependency to the caller
}
public override IDependency Dependency
{
get { return _dependency; }
}
}
public interface ITypeAFactory
{
TypeA CreateInstance(Type typeOfA);
}
public class ConcreteTypeAFactory : ITypeAFactory
{
private readonly IUnityContainer _container;
public ConcreteTypeAFactory(IUnityContainer container)
{
_container = container;
}
public TypeA CreateInstance(Type typeOfA)
{
return _container.Resolve(typeOfA) as TypeA;
}
}
public class TypeARepository
{
private readonly ITypeAFactory _factory;
public TypeARepository(ITypeAFactory factory)
{
_factory = factory;
}
public TypeA GetById(int id)
{
// As per Ewan, some kind of Strategy Pattern.
// e.g. fetching a record from a database and use a discriminating column etc.
return (id%2 == 0)
? _factory.CreateInstance(typeof (TypeB))
: _factory.CreateInstance(typeof (TypeC));
// Set the properties of the TypeA from the database after creation?
}
}
class Program
{
static void Main(string[] args)
{
// Unity Bootstrapping
var myContainer = new UnityContainer();
myContainer.RegisterType<ISpecializedDependencyForB, ConcreteDependencyForB>();
myContainer.RegisterType<ISpecializedDependencyForC, ConcreteDependencyForC>();
myContainer.RegisterType(typeof(TypeB));
myContainer.RegisterType(typeof(TypeC));
var factory = new ConcreteTypeAFactory(myContainer);
myContainer.RegisterInstance(factory);
myContainer.RegisterType<TypeARepository>(new InjectionFactory(c => new TypeARepository(factory)));
// And finally, your client code.
// Obviously your actual client would use Dependency Injection, not Service Location
var repository = myContainer.Resolve<TypeARepository>();
var evenNumberIsB = repository.GetById(100);
Debug.Assert(evenNumberIsB is TypeB);
Debug.Assert(evenNumberIsB.Dependency is ISpecializedDependencyForB);
var oddNumberIsC = repository.GetById(101);
Debug.Assert(oddNumberIsC is TypeC);
Debug.Assert(oddNumberIsC.Dependency is ISpecializedDependencyForC);
}
}
}
Could whatever it is that knows about the dependencies live behind an interface IDependencyProvider which has a function
IDependency GetDependency(Type type).
This could even just return an object and the class that realises the interface needs to know all the sub types and their associated dependencies.
AbstractMethod is then changed to:
void AbstractMethod(IDependencyProvider provider);
In your sub classes you then override this and call
var dependency = provider.GetDependency(this.GetType());
Your middle tier then knows nothing about the sub types or the sub dependencies.
It's an interesting problem, what I was thinking is that your repository knows about and creates the TypeB and TypeC classes and so you can add the correct dependency at that point
public class TypeARepository
{
private ISpecializedDependencyForB depB;
private ISpecializedDependencyForC depC;
public TypeARepository(ISpecializedDependencyForB depB, ISpecializedDependencyForC depC)
{
this.depB = depB;
this.depC = depC;
}
public TypeA GetById(string id)
{
if (id == "B")
{
return new TypeB(depB);
}
else
{
return new TypeC(depC);
}
}
}
The TypeB and TypeC would then implement their abstract methods with their private ref to the dependency rather than having it passed in in the method.
I come across this problem in various forms myself from time to time and it always seems to me that if there is that hard link between the types just having it setup via an injection config or the like is wrong. As it allows the installer to potentially set a bad config
This approach also allows you to inject your dependencies with unity
Thank you a lot for your interest in my question, I came up with a solution yesterday evening. The objective is to keep things transparent for the client and to take full advantage of polymorphism by syntaxes such as baseObjectReference.AbstractMethodCall().
I finally realized that I was able to achieve what I'm after by taking advantage of the static modifier and using it for DI purposes. So I have that :
public abstract class TypeA
{
public abstract void AbtractMethod();
}
public class TypeB : TypeA
{
private ISpecializedDependencyForB SpecializedDependencyForB
{
get
{
return GetSpecializedDependencyForB.CreateSpecializedDependencyForB();
}
}
public override void AbtractMethod() { // do stuff with dependency }
}
public static class GetSpecializedDependencyForB
{
public static ISpecializedDependencyForB DependencyForB
{
return CreateSpecializedDependencyForB();
}
public delegate ISpecializedDependencyForB CreateSpecializedDependencyForBDelegate();
public static CreateSpecializedDependencyForBDelegate CreateSpecializedDependencyForB;
}
And then, in my unity container I add this code :
public static void RegisterTypes(IUnityContainer container)
{
// .... registrations are here as usual
GetSpecializedDependencyForB.CreateSpecializedDependencyForB = CreateMyDomainService;
}
Having this method in the same unity config class :
private ISpecializedDependencyForB CreateMyDomainService()
{
return container.Value.Resolve<ISpecializedDependencyForB>();
}
And finally, I can simply use my object like this :
TypeA myDomainObject = database.TypeARepository.GetById(id);
myDomainObject.AbtractMethod();
And that's it !
So four things here :
The first one is that I inject the delegate that will create and instance of the service.
Then it is thread safe because static member is only written one time at the beginning of the application. All other accesses will be read. Moreover two threads won't share the same instance of the dependency since the delegate creates a new one all the time.
Also one interesting thing is that I can rely on my existing unity container configuration, no extra code is needed. It is important because my dependency may need other dependency to be constructed.
And finally the unity container is anyway also static, so there is no memory leak.
It's basically a manual and easy to set up "DI framework" sitting beside Unity.
And more importantly it works like a charm ! I'm finally satisfied with my design. I will only use this approach for polymorphic situations since injecting the right dependency in the method is easy for other situations. However it might be interesting to fully encapsulate the domain model using this approach.
EDIT: I've cleaned this question up significantly after solving my problem, including changing the title.
I have a MessageChannel interface which defines (unsurprisingly) a channel that my classes can use to push messages to the end user.
Normally this MessageChannel is a Singleton and is bound to a ViewModel that implements the MessageChannel interface. Essentially, there is a single location at the top of my application where messages to the user will be shown. So far its worked pretty well.
This MessageChannel is used in a lot of places, one of which is in some operation classes that I have setup.
I now have a need for a LOCAL MessageChannel, such messages being posted in some reduced scope get posted to that local MessageChannel and not the global one.
What this means is that I need to be able to create instances of a ViewModel (through a Factory), such that that particular instance has its own MessageChannel instance AND that MessageChannel instance is shared for all dependencies injected into that ViewModel (and their dependencies and so on).
Some classes to illustrate. I have simplified things somewhat, my messages are more than just strings:
using Ninject;
using Ninject.Extensions.Factory;
public interface MessageChannel
{
void PostMessage(string message);
}
public class MessageChannelViewModel : MessageChannel
{
public string Message { get; set; }
public void PostMessage(string message)
{
Message = message;
}
}
public interface Operation
{
void Do();
}
public interface OperationFactory
{
Operation Create();
}
public class DefaultOperation : Operation
{
public DefaultOperation(MessageChannel userMessages)
{
_UserMessages = userMessages;
}
private readonly MessageChannel _UserMessages;
public void Do()
{
// Do something.
_UserMessages.PostMessage("Success!");
}
}
public interface IsolatedViewModel
{
MessageChannelViewModel LocalMessages { get; }
}
public interface IsolatedViewModelFactory
{
IsolatedViewModel Create();
}
public class DefaultIsolatedViewModel : IsolatedViewModel
{
public IsolatedViewModel(MessageChannelViewModel localMessages, OperationFactory opFactory)
{
_OpFactory = opFactory;
LocalMessages = localMessages;
}
private readonly OperationFactory _OpFactory;
public MessageChannelViewModel LocalMessages { get; private set; }
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<MessageChannel, MessageChannelViewModel>().To<MessageChannelViewModel>().InSingletonScope();
Bind<Operation>().To<DefaultOperation>();
Bind<OperationFactory>().ToFactory();
Bind<IsolatedViewModel>().To<DefaultIsolatedViewModel>();
Bind<IsolatedViewModelFactory>().ToFactory();
// Something to make it so the IsolatedViewModel DOESNT get the Singleton
// instance of the MessageChannelViewModel, and instead gets once of its own
// AND so the Operations created by the OperationFactory injected into the
// IsolatedViewModel get the SAME MessageChannel, so messages being posted
// from any place in the IsolatedViewModel's dependencies are shown only\
// locally.
}
}
I tried the NamedScope extension but I couldn't get it do what I wanted it to do.
I think you can try to use The Ninject Context Preservation Extension which adds support for recording (and making available to Contextual Binding rules) the context pertaining to factories that call the Kernel to Resolve Requests.
This enables you to add contextual conditions to your Bindings.
I ended up using a combination of Ninject.Extensions.ContextPreservation and Ninject.Extensions.NamedScope to accomplish what I wanted.
The completed example module looks like this:
public class Module : NinjectModule
{
public override void Load()
{
Bind<MessageChannel, MessageChannelViewModel>().To<MessageChannelViewModel>().InSingletonScope();
Bind<Operation>().To<DefaultOperation>();
Bind<OperationFactory>().ToFactory();
var uniqueName = "UNIQUE";
Bind<IsolatedViewModel>()
.To<DefaultIsolatedViewModel>()
.Named(uniqueName)
.DefinesNamedScope(uniqueName);
Bind<MessageChannel, MessageChannelViewModel>().To<MessageChannelViewModel>()
.WhenAnyAncestorNamed(uniqueName)
.InNamedScope(uniqueName);
Bind<IsolatedViewModelFactory>().ToFactory();
}
}
Theres two parts to it.
You need the ContextPreservation extension to choose the correct binding based on the context available at the time that you resolve the object instance. In this case I used a name as context, meaning that my special MessageChannel binding will be used when resolving the MessageChannel dependency for any dependencies required under the IsolatedViewModel.
I needed the NamedScope extension to ensure that only 1 instance of the MessageChannel was created under each IsolatedViewModel instance (i.e. the instance was shared for that IsolatedViewModel and all its dependencies).
Some other things to be aware of:
If you are using any ToMethod bindings and you use the Kernel inside the method, you'll need to make sure you use a ContextPreservingGet or you'll lose your context and the correct binding wont be selected.
You'll have to look very closely at your bindings and double check any Singleton bindings because if any of the dependencies of your isolated class are bound in Singleton scope, and they have dependencies on the MessageChannel (for example) its not going to work like you want it to. I had to remove a couple of Singleton scoped bindings as a result of this (for the better probably).