Prism, connecting Views and ViewModels with Unity, trying to understand it - c#

Creating the View and View Model Using Unity
Using Unity as your dependency injection container is similar to using
MEF, and both property-based and constructor-based injection are
supported. The principal difference is that the types are typically
not implicitly discovered at run time; instead, they have to be
registered with the container.
Typically, you define an interface on the view model so the view
model's specific concrete type can be decoupled from the view. For
example, the view can define its dependency on the view model via a
constructor argument, as shown here. C#
public QuestionnaireView()
{
InitializeComponent();
}
public QuestionnaireView(QuestionnaireViewModel viewModel) : this()
{
this.DataContext = viewModel;
}
The default parameter-less
constructor is necessary to allow the view to work in design-time
tools, such as Visual Studio and Expression Blend.
Alternatively, you can define a write-only view model property on the
view, as shown here. Unity will instantiate the required view model
and call the property setter after the view is instantiated. C#
public QuestionnaireView()
{
InitializeComponent();
}
[Dependency]
public QuestionnaireViewModel ViewModel
{
set { this.DataContext = value; }
}
The view model type is registered with the Unity container, as shown
here. C#
IUnityContainer container;
container.RegisterType<QuestionnaireViewModel>();
The view can then be instantiated through the container, as shown
here. C#
IUnityContainer container;
var view = container.Resolve<QuestionnaireView>();
If I leave out the last part of the code regarding registering the ViewModel and instantiating the View, and just use either of the two methods of hooking the ViewModel to the View here (using a constructor or using a property) it seems the ViewModel and View it seems everything is working fine. So what is the need for the code registering the ViewModel and instantiating the View?
The first example, hooking the View and ViewModel using a constructor, has no mention of Unity of all, so is Unity actually being used here?
Are there any advantages of using property-based injection over construtor based injection or are they exactly the same thing?
The first part of the text says "*Typically, you define an interface on the view model so the view model's specific concrete type can be decoupled from the view", and then gives an example. Yet this example makes no mention of interfaces at all. What is going on here, am I missing something?

To answer questions 1 & 4
In your example, the viewmodel is of type QuestionnaireViewModel, which is a concrete class. Since it's a concrete class, when you resolve the view using container.Resolve<QuestionnaireView>(), unity will instantiate the viewmodel for you by calling container.Resolve<QuestionnaireViewModel>() behind the scenes.
In this case, registering your viewmodel is redundant. However, when using dependency injection you usually want to work with interfaces rather than classes, so your constructor would look like this:
public QuestionnaireView(IQuestionnaireViewModel viewModel)
{
this.DataContext = viewModel;
}
Now that your constructor receives an interface rather than a class as a parameter, Unity doesn't know which implementation of the interface you'd like to use. To tell Unity that, you need to register your viewmodel to the container:
container.RegisterType<IQuestionnaireViewModel, QuestionnaireViewModel>();
so now when you resolve your view, Unity will look up which class it should use as an implementation of IQuestionnaireViewModel, see that it's QuestionnaireViewModel and use it.
To answer question 2
Unity is being used, since in order for the constructor to get its parameters, you need to resolve the view using the container. Unity is not used if you instantiate the view yourself using new QuestionnaireView(), i.e. no constructor or property injection will occur.
To answer question 3
I think it's mostly a matter of what's more comfortable and where you need to use the injected members. A lot of times you just want to set a local variable in the constructor and not create a property just for performing the injection.
One good thing about property-injection though is the fact that you can use the container.BuildUp() method for instances that were created by using new rather than container.Resolve<>(). This way, you can inject members into properties even after creation - which is something you can't do with constructor injection.

Related

Correct way to use DI when creating new objects in Collection

MVVM, using PRISM 6 and Unity.
Bootstrapper takes care of creating intial View, which is in turn AutoWired to the ViewModel (i.e. View Model is resolved and it's DI's are taken care of).
Now the View Model has a Collection of other View Models.
This Collection can be added to with User Input, say with a button push.
The View Models in the collection require access to a singleton that I have to manage the "Workspace" (paths for image folders etc). So I would also want the creation of those objects to have that "Workspace" singleton injected into it.
In the method that would create a new ViewModel, what's the correct way to utilize DI/IoC to create it?
The only way I see it (dangerous to say "only" I know, that's why I'm asking for help) is:
Inject the Unity Container into the View Model that contains the
collection, then Resolve the new View Models as the button is hit.
The new View Models would be setup with a dependency on the
interface for the "Workspace" object.
Create a new View Model when the button is hit and pass the
"Workspace" into the constructor (of course the Workspace would need to be DI'd into the parent View Model to be passed down).
I have read multiple places that getting into passing the Container down via DI so that one can use Resolve<> isn't "correct".
Is this where creating a generic Factory would help? This still forces me to pass the container down, now it's just in the form of a factory though...
public T factory<T>(IContainer _container)
{
return _container.Resolve<T>();
}
Often when I read about DI, it is treated as the be all and end all. I more often than not use IoC heavily even in my small and simple projects, however, it is just pattern and has a place like everything else.
The Microsoft Press book Adaptive Code via C# explains SOLID well, justifies its use, covers the various forms of DI and the cost/benefit of each technique. For me, it made a lot of sense of these issues, managing project growth, and dealing with external dependencies.
I would NOT pass the UnityContainer to anything outside of my bootstrapper, other than a system which abstracts and breaks apart the bootstrapping/modularity process. In addition to the points you have made about this, Unity is a third-party dependency to your application just like anything else, and I would be very selective of which (if any) I tie myself to.
For your example above, I would use a simple factory. You could abstract this as far as you like, but a good compromise would be relieving your primary ViewModel of the burden of having to create its own children.
When using DI, there is nothing wrong with instantiating things yourself where appropriate. The most appropriate place of course is a factory. I wouldn't create a generic factory, as you stated, this is basically just like passing around the IoC container. Define a typed factory instead:
public interface IWorkspaceItemViewModelFactory
{
WorkspaceItemViewModel CreateWorkspaceItem();
}
The implementation of this might look something like this:
public class WorkspaceItemViewModelFactory
{
private readonly IWorkspaceManager _workspaceManager;
public WorkspaceItemViewModelFactory(IWorkspaceManager workspaceManager)
{
_workspaceManager = workspaceManager;
}
public WorkspaceItemViewModel CreateWorkspaceItem()
{
return new WorkspaceItemViewModel(_workspaceManager);
}
}
This class is an information expert with the single responsibility of creating WorkspaceItemViewModel instances. It has the right the use the new keyword, and have knowledge of WorkspaceItemViewModel dependencies. You may wish to insulate the ViewModel with an interface, but the value might be very little in your use case. Ultimately, you are using IoC, DI, and Interface Segregation for a reason, and when they stop delivering value to your particular application their use becomes noise.
Your view model could make use of this something like:
public class ExampleViewModel : ViewModelBase
{
public ExampleViewModel(IWorkspaceItemViewModelFactory workspaceItemViewModelFactory)
{
AddItemCommand = new ActionCommand(() =>
{
var newItem = workspaceItemViewModelFactory.CreateWorkspaceItem();
WorkspaceItems.Add(newItem);
});
}
public ICommand AddItemCommand { get; }
public ObservableCollection<WorkspaceItemViewModel> WorkspaceItems { get; } = new ObservableCollection<WorkspaceItemViewModel>();
}

Simple Injector - register collection

I use Simple Injector to create IoC container. I took pattern here:
Page Navigation using MVVM in Store App
As I asked in comment to above post, I would like to register collection of INavigationPage. I did it like that:
private static void RegisterNavigationPages()
{
Container.RegisterCollection<INavigationPage>(new []
{
typeof(MainNavigationPage),
typeof(SecondNavigationPage)
});
}
Inside the container I have ViewModels and NavigationService to:
Container.Register<INavigationService, NavigationService>(Lifestyle.Singleton);
Container.Register<IMainViewModel, MainViewModel>(Lifestyle.Singleton);
Container.Register<ISecondViewModel, SecondViewModel>(Lifestyle.Singleton);
This is way how I set DataContext of page:
DataContext = App.Container.GetInstance<IMainViewModel>();
Everything is OK but I want to use NavigationPages from that collection inside my ViewModel constructor. I can do it by index:
public SecondViewModel(INavigationService navigationService, IEnumerable<INavigationPage> navigationPageCollection)
{
NavigationService = navigationService;
_navigationPage = (navigationPageCollection.ToList())[0];
GoToMainPageCommand = new Command(GoToMainPageAction);
}
but it isn't elegant solution because when I change order of NavigationPages I will have to change all indexes in whole application. Is it any solution when I will can recognize which NavigationPage I want to use in ViewModel constructor?
I can't do it by typeof, because that NavigationPage types are in UIProject and I can't have reference there from ViewModel project because of circular reference dependency.
Currently the correctness of the SecondViewModel is completely dependent on the order and filling of the navigationPageCollection, which makes it really fragile. If your SecondViewModel needs a MainNavigationPage, that's what you should inject. Don't inject a collection; inject the page itself. That probably means that MainNavigationPage needs its own interface, such as IMainNavigationPage. That removes any ambiguity that you are having right now. But instead of having loads of one-to-one mapping non-generic interface (a violation of the RAP principle), you might be better of defining a few generic abstractions.
I have a similar problem and have solved this issue before. Read my blog here clean factory pattern
Basically what you need is to add a method or property to identify the user in the INavigationPage, and then also add the same identifier in the SecondViewModel. The SecondViewModel constructor just need to iterate through the IEnumerable and find the page that it needs.

How to inject dependencies into view models in Caliburn.Micro?

I really hope this is not a stupid question, but I'm somehow unable to recognize a straight-forward way to inject dependencies into view models using Caliburn.Micro.
I'm having a main shell (conductor) like so:
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShell
{
public ShellViewModel(IEventAggregator eventAggregator) {
ActivateItem(new DashboardViewModel());
}
}
Now I'd like to inject a service into the DashboardViewModel but since the ActivateItem method requires me to pass an instance (rather than e.g. a type), I'm forced to provide the service myself. And since the ShellViewModel isn't aware of an underlying IoC container, I have to have the service injected into the shell.. to me, it looks like Caliburn is trying to enforce a complete graph of all view models and dependencies within an application.
I am aware that I could use a static accessor for my inversion of control container, but I really don't like this approach because I'd like to have a single composition root for my application (the bootstrapper) without having the other parts knowing about dependency injection and such.
couple of ways to do it dependent completely on your choice of container.
MEF [ImportMany] used in the constructor on the parameter that will do the actual import reference the Hello Screens example
The baked in IoC static class you could use IoC.Get<IDashBoard>() or IoC.GetAll<IDashBoard>(), this assumes you have register your types into the container you use. Caution with this one it can be over used and result in anti-pattern behavior. I have done this in one of my apps that does a dashboard, anything that is tagged with IDashBoard in my Container instance, in association with the actual implementation class will get pulled into the collection IoC.GetAll<IDashboard>() or the first item in the collection based on the IoC.Get<IDashBoard>().
You could also make your dashboard inherit Conductor<IDashBoard>.Collection.AllActive, there by allowing you access to the Items property (as part of the Collection) and populate it with the CTOR of your DashBoardViewMode, using IoC.GetAll<IDashboard>() in that one place get all the items you need on your dashboard. From there, I query the Items collection property in OnActivate and match the other viewmodels to the properties that I needed and placed named ContentControls on the DashBoardView accordingly.
this does pull from the container that you have chosen, keeping that in mind you might just want to you the containers' methods to grab the necessary items through its intended design.
I actually moved away from MEF since version used in CM doesn't work with Open Generics and debugging missing Export() attributes was starting to wear me out.

Ideal number of Object Instances to pass Via View Model constructor (dependency injection)

I am implementing a project, main objective is to have loosely coupled class implementations, for example below, i am using simple IOC container to inject PageNavigation and AppConfig instance into the view model.
public MyViewModel(IPageNavigationService PageNavigation, IAppConfig AppConfig) {
//my code
}
is there a limit to number of instances i can pass via constructor? , which may cause unforeseen problems .
what if i would have 5 to 6 object instances i need to pass, is there any other way i can access the object instance other than constructor, keeping things loosely coupled and dynamic, and all View model's using default instance (singleton ) of the object being passed.
There is no limit of instances to pass to your viewmodel instance via a constructor. You should pass all dependencies, that are required for your ViewModel to work properly via the constructor.
Dependencies that are optional or providing a diffrent implementation can be passed by PropertyInjection.
You could also define a constructor to get a reference to the IOC-Container, so that the ViewModel resolves the necessary dependencies by itself in the constructor. But then has your viewmodel a dependency to the container what is not required sometimes.
public MyViewModel(IocContainer container) {
// resolve dependencies via the container
}

MVVM and Dependency Injection

I am currently learning the MVVM pattern, and the tutorial I am following uses Unity for DI. I haven't really used DI in this way before and just wanted clarification of my thoughts on how this specific code works.
In the View I have:
private ViewModel vm;
[Dependency]
public ViewModel VM
{
set
{
vm = value;
this.DataContext = vm;
}
}
where the dependency attribute is telling Unity to inject here. The ViewModel constructor takes an IQuoteSource object which is registered with Unity as such:
IUnityContainer container = new UnityContainer();
RandomQuoteSource randomQuoteSource = new RandomQuoteSource();
container.RegisterInstance<IQuoteSource>(randomQuoteSource);
MainWindow window = container.Resolve<MainWindow>();
window.Show();
How exactly does this work, as I am never explicitly creating an object of the ViewModel using the property above. Is this all handled within Unity, if so how does it achieve this?
Thanks.
This doesn't have much to do with the MVVM pattern per se, other than the fact that the view's dependency on its ViewModel is resolved via dependency injection.
For how this works, it's pretty simple. There are 3 simple concepts for DI:
The first is declaring a dependency, where some object specifies that it depends on something, either via a constructor or a property (which was the case in your example, using the DependencyAttribute).
The second concept is registration, where you register an implementation of the dependencies your objects have (in your case, you registered an implementation of the IQuoteSource). Note that you didn't have to register the ViewModel, because it's not really an implementation of an interface that you depend on.
The third is what glues things together, which is resolving the dependencies, where you ask the container to resolve some type for you, and it goes and looks at what dependencies that object declared (in your case, you're resolving the MainWindow which has a dependency on the ViewModel), finds the right registered implementation and resolves it. This behavior cascades through the resolution of the graph of objects (which resolves the dependency of the ViewModel on the IQuoteSource).
Hope this helps :)
Is it MainWindow which the VM property belongs to? If not I'm assuming that resolving a MainWindow starts some sort of resolve cascade which at some point includes creating the object which has the VM property in your example.
Unity examines each object it has to resolve within the cascade for properties decorated with [Dependency], and creates an object of the dependent property type. When it creates objects like this it picks the constructor which has the most parameters it knows how to create, which is where your registration of IQuoteSource -> RandomQuoteSource comes in.

Categories