I have WPF Project with Prism 7.1, Unity DI 5.8.11 and .NET framework 4.7
I have BaseViewModel
which all the ViewModel classes will inherit from
public abstract class BaseViewModel : BindableBase
{
[Dependency]
protected IEventAggregator EventAggregator { get; set; }
// just default constructor, no other constructor is needed
}
and here is an example of one of the ViewModel class
public class TablesViewModel : BaseViewModel
{
public TablesViewModel()
{
EventAggregator.GetEvent<OperatorChangedEvent>().Subscribe(.....);
}
}
and the register of the type as the following
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterInstance<IEventAggregator>(new EventAggregator());
}
Now, what happened is the following: First the constructor of the BaseViewModel
is called then the constructor of the TablesViewModel
then the Dependency property is set by the Unity DI, this is a logical sequence of events, but it does not fit for me.
the constructor of the TablesViewModel
is giving a null reference Exception because the EventAggregator
property is still null.
I do not want to use the constructor dependency injection, this will force me to create a lot of non-default constructor for all the ViewModel classes.
and at the same time, I need to subscribe to the EventAggregator
at the constructor ( because there is no other good place to do that if there is please told me).
How can I solve this
I do not want to use the constructor dependency injection, this will force me to create a lot of non-default constructor for all the ViewModel classes.
You want non-default constructors for classes that have dependencies. That's what dependency injection is all about: the types tell the user through their constructor parameters what he has to give them to operate.
There are plenty of ways to create view models with non-default constructors, e.g. Prism's ViewModelLocator
or Unity's automatic factories. You do not want to resort to using the ServiceLocator
unless it is absolutely necessary, but an evil person technically could do something like this:
public abstract class BaseViewModel : BindableBase
{
protected IEventAggregator EventAggregator { get; } = ServiceLocator.Current.GetInstance<IEventAggregator>();
}