MVVM Light SimpleIoc - c#

I'm using WPF with MVVM Light in my project. I have some small question about SimpleIoC containter and DI. Which is the better way to use it or tell me if I don't need to use DI there.
There is my VM constructor:
public MainViewModel(IDialogService dialogService, IChannelObserverService channelObserverService, IInternalBroadcastService internalBroadcastService,
IUserDataAccessService userDataAccessService, IUserService userService)
And SimpleIoC register:
SimpleIoc.Default.Register<MainViewModel>(() => {
return new MainViewModel(SimpleIoc.Default.GetInstance<IDialogService>(),
SimpleIoc.Default.GetInstance<IChannelObserverService>(),
SimpleIoc.Default.GetInstance<IInternalBroadcastService>(),
SimpleIoc.Default.GetInstance<IUserDataAccessService>(),
SimpleIoc.Default.GetInstance<IUserService>()); });
Please tell me, do I need to use DI there?
First I had using all services like this:
public MainViewModel(){...}
User user = SimpleIoc.Default.GetInstance<IUserService>().GetCurrentLoggedUser();
or this:
private IDialogService dialogService;
public MainViewModel()
{
dialogService = = SimpleIoc.Default.GetInstance<IUserService>();
}
private void MyMethod()
{
dialogService.ShowQuestionDialog(abc,abc,abc);
}
So I didn't use DI when I was creating my View-Models.

I'd recommend you to use the DI as it enables the development of loosely coupled code. Through DI, you can decrease tight coupling between software components. Also, it makes unit testing convenient.
I would suggest to have constructor like this (as you have mentioned in your post)
public MainViewModel(IDialogService dialogService, IChannelObserverService channelObserverService, IInternalBroadcastService internalBroadcastService,
IUserDataAccessService userDataAccessService, IUserService userService)
But registration can be simplified as
SimpleIoc.Default.Register<IDialogService, DialogService>();
//// Other service registrations.
SimpleIoc.Default.Register<MainViewModel>(); // without injecting the other dependent types.
With this DI will take to inject the right dependencies while creating an instance of MainViewModel.
So with this above approach, you don't need to Resolve the instance inside your code as it is already inject in constructor, so service code can be simplified as
private void MyMethod()
{
dialogService.ShowQuestionDialog(abc,abc,abc);
}

Related

WPF : How to do dependency injection when ViewModels and Views are in separate projects?

I have this WPF app with MVVM pattern, now I want to do dependency injection in my project, but I found myself in trouble. My App has below construction:
MyApp
|----MyApp.ViewModels
|----MyApp.Views
According to this doc, I need to initiate my dependency injection services in the App.Xaml.cs file which is in MyApp.Views project.
Say I have two viewmodels in MyApp.ViewModels project:
public class ViewModelAlpha{
private IDialogService _dialogService;
private ViewModelBeta viewModelBeta;
public ViewModelAlpha(IDialogService dialogService){
_dialogService = dialogService;
}
}
public class ViewModelBeta{
private IDialogService _dialogService;
public ViewModelBeta(IDialogService dialogService){
_dialogService = dialogService;
}
}
So, ViewModelAlpha has a ViewModelBeta singleton as its field, what should I do to lazy initiate ViewModelBeta in ViewModelAlpha? I don't want to initiate ViewModelBeta until it's required. What I'm currently doing is provide a static Instance in ViewModelBeta:
public class ViewModelBeta{
private static ViewModelBeta instance;
public static ViewModelBeta Instance {
return instance ?? new ViewModelBeta();
}
public ViewModelBeta(){ ... }
}
What I can think of is to change the Instance property to something like :
public static ViewModelBeta Instance {
return instance ??
ServiceProvider.GetRequiredService<ViewModelBeta>();
}
But since ServiceProvider is created in the MyApp.Views project, how should I get it in MyApp.ViewModels project.
I found this answer for a similar question I had, for a similar use case, was quite helpful.
Generically Register All Concrete types for Lazy Loading in DI
The end result is you can register an IYourInterface and it will also register a Func<IYourInterface> you can inject and invoke when ready to load it.
All the Func<T> does is request that same interface from the DI engine, allowing you to lazy load it.
In my case it was registering all the Window classes I had implemented in my assembly, but it can be applied to any use case, the handy answer is a nice generic way that utilizes expression reflection to compose the Func<T> on the fly.
You can see here in another of my projects I extended the functionality out to create a suite of similar methods for all the standard registrations on ServiceCollection
https://github.com/SteffenBlake/PoeFilterX/blob/main/src/PoeFilterX/Extensions/ServiceCollectionExtensions.cs
I have faced the same problem before where some dependencies might cost extra memory to initiate at the constructor, in your case, view models.
In general, this problem might be similar to transient services where you in some situations will resolve them using IServiceProvider.GetRequiredService<T>() and soon after getting rid of their references for less memory consumption.
And to use the service provider, the best way is to inject it into your service constructor as a dependency, so for the case of your view model:
public ViewModelAlpha(IDialogService dialogService, IServiceProvider serviceProvider)
{
_dialogService = dialogService;
_serviceProvider = serviceProvider;
}
And then you can add a property to lazy load ViewModelBeta whenever needed:
public class ViewModelAlpha
{
private ViewModelBeta? _viewModelBeta;
private ViewModelBeta ViewModelBeta
{
get => _viewModelBeta ??= _serviceProvider.GetRequiredService<ViewModelBeta>();
}
// Dependencies.
private IDialogService _dialogService;
private IServiceProvider _serviceProvider;
public ViewModelAlpha(IDialogService dialogService, IServiceProvider serviceProvider)
{
_dialogService = dialogService;
_serviceProvider = serviceProvider;
}
}
But since ServiceProvider is created in the MyApp.Views project, how
should I get it in MyApp.ViewModels project.
Having the ServiceProvider injected into your startup project (MyApp.Views) doesn't mean that core library services can't have it as a dependency. In fact, it's a common design for core services that are separated away from the startup project to loudly state that "Any project that requires our services must provide us with some necessary dependencies first".
Those dependencies would be required as a form of an interface implementation, so when the core library uses IMyService, the startup project should inject its own implementation of IMyService, say MyService.
A good example is the IHostApplicationLifetime service that is part of the .Net Generic Host. In a lot of cases, you might want to shut down the application from within your view model, and to do so you will need to call IHostApplicationLifetime.StopApplication() which does the job.

Correctly use Dependency Injection pattern [duplicate]

I'm currently working on a WinForms system (I know) where there's a lot of Constructor Injection when creating forms, but if those forms/views need to open another form, I find the DI container has been injected too so that we can locate the implementation of the desired view interface at runtime. e.g.
public partial class MyView : Form, IMyView
{
private readonly IDIContainer _container;
public MyView(IDIContainer container)
{
InitializeComponent();
_container = container;
}
public OpenDialogClick(object sender, EventArgs e)
{
var dialog = container.Resolve<IDialogView>();
dialog.ShowDialog(this);
}
}
I'm aware that this is basically using the container as a service locator. I've been repeatedly told that this is considered an anti-pattern so I'd like to avoid this usage.
I could probably inject the view as part of the constructor like this :
public partial class MyView : Form, IMyView
{
private readonly IDialogView _dialog;
public MyView(IDialogView dialog)
{
InitializeComponent();
_dialog = dialog;
}
public OpenDialogClick(object sender, EventArgs e)
{
dialog.ShowDialog(this);
}
}
But what if the dialog view is quite expensive to instantiate?
It's been suggested that we create some kind of form factory which internally uses the DI container, but to me this seems like simply creating a wrapper around another service locator.
I know that at some point, something has to know how to create an IDialogView, so I'm thinking that either it's resolved when the composite root is created (probably not ideal if there are many forms and some or all are expensive to create), or the composite root itself has a way to resolve the dependency. In which case the composite root has to have a service-locator-like dependency? But then how would child forms create dialogs like this? Would they call up to the composite via, say, events, to open dialogs like this?
One particular problem I keep running up against is that the container is almost impossible to mock easily. This is partly what keeps me thinking about the form factory idea, even though it would just be a wrapper around the container. Is that a sensible reason?
Have I thought myself into a knot? Is there a simple way through this? Or do I just cut the knot and find something that works for me?
Or do I just cut the knot and find something that works for me?
Factory class:
public interface IDialogFactory {
IDialogView CreateNew();
}
// Implementation
sealed class DialogFactory: IDialogFactory {
public IDialogView CreateNew() {
return new DialogImpl();
}
}
// or singleton...
sealed class SingleDialogFactory: IDialogFactory {
private IDialogView dialog;
public IDialogView CreateNew() {
if (dialog == null) {
dialog = new DialogImpl();
}
return dialog;
}
}
Your code:
public partial class MyView : Form, IMyView {
private readonly IDialogFactory factory;
public MyView(IDialogFactory factory) {
InitializeComponent();
//assert(factory != null);
this.factory = factory;
}
public OpenDialogClick(object sender, EventArgs e) {
using (var dialog = this.factory.CreateNew()) {
dialog.ShowDialog(this);
}
}
}
Registration with SimpleInjector
container.RegisterSingle<IDialogFactory, DialogFactory>();
or using singleton version
container.RegisterSingle<IDialogFactory, SingleDialogFactory>();
container.RegisterSingle<IMyView, MyView>();
A local factory, satisfied with an implementation that uses the container and set up in the composition root is not a service locator, it is a dependency resolver.
The difference is as follows: the locator is defined and satisfied somewhere near the definition of the container. In a separate project, to use the locator, you need an external reference to the container infrastructure. This causes the project to rely on external dependency (the locator).
On the other hand, the dependency resolver is local to the project. It is used to satisfy dependencies in its close neighbourhood but it doesn't depend on anything external.
The composition root should not be used to resolve actual specific dependencies such as the one you are concerned about. Instead, the compositon root should set up implementations of all these local dependency resolvers that are used throughout the application. The more local resolver, the better - the MVC's constructor factory is a good example. On the other hand, WebAPI's resolver handles quite few of different services and it is still a good resolver - it is local in the webapi infrastructure, it doesn't depend on anything (rather - other webapi services depend on it) and it can be implemented in any possible way and set up in the Composition Root.
Some time ago I wrote a blog entry about it
http://www.wiktorzychla.com/2012/12/di-factories-and-composition-root.html
There you will find your issue discussed and an example of how you set up a factory aka resolver.
You definitely do not want to pass your DI container around your application. Your DI container should only be part of your Composition Root. You could, however, have a factory that uses the DI container within the Composition Root. So if Program.cs is where you are wiring everything up, you could simply define that factory class there.
WinForms was not designed with DI in mind; forms are generated and therefore need default constructors. This may or may not be an issue depending on which DI container you use.
I think in this case, the pain of using constructor injection in WinForms is greater than the pain of any pitfalls you may encounter while using a service locator. There's no shame in declaring a static method in your Composition Root (Program.cs) that wraps a call to your DI container to resolve your references.
I know this problem very well. Everything I learned about solution to this (and I learned A LOT) is more or less camouflaging service locator.

How do i abstract my DI tool from UI/Service layer

this question is a follow-up of this question i posted last weekend.
As of now, i have something like this in my service layer which talks with UI in MVC application.
IDepartmentService deptService = kernel.Get<IDepartmentService>();
IList<Department> deptList = deptService.GetAllDepartments();
Everything is fine and DI is working as expected. However, for some reason if i decide to use Structuremap then my entire service layer needs to be changed. How do i abstract it out so that a change in DI tool wont affect my service layer or has minimum impact.
However, for some reason if i decide to use Structuremap then my
entire service layer needs to be changed.
That's not true. As shown in the previous thread the Service Layer doesn't know anything about the DI framework.
You should have a layer called composition root. This is the only layer which is aware of the DI framework and all the underlying layers. This is where you are doing the composition. So if you change the DI framework, the only place you need to make changes is in the composition root.
So you should absolutely get rid of kernel.Get<> calls from your service. Right now you are using Service Locator and not Dependency Injection. Service Locator is an anti-pattern. Your service layer should look like this:
public class MyService
{
private readonly ISomeDependency dependency;
public MyService(ISomeDependency dependency)
{
this.dependency = dependency;
}
public void SomeMethod()
{
// do something with the dependency here
}
}
instead of:
public class MyService
{
private readonly ISomeDependency dependency;
public MyService()
{
this.dependency = kernel.Get<ISomeDependency>();
}
public void SomeMethod()
{
// do something with the dependency here
}
}

Get the container instance for Simple Injector

I am using Simple Injector with a ASP.NET MVC project. I added the SimpleInjector.Integration.Web.Mvc nuget package. This adds SimpleInjectorInitializer class in App_Start folder and initializes the DI. The code looks something like
public static void Initialize()
{
// Did you know the container can diagnose your configuration?
// Go to: https://simpleinjector.org/diagnostics
var container = new Container();
//Container configuration code
DependencyResolver.SetResolver(
new SimpleInjectorDependencyResolver(container));
}
This configures the DI for the MVC controller correctly.
My question is, if I want to get the instance of the container in any of the controller\class to resolve some dependency manually how can I do it.
I have earlier worked on AutoFac and it has a dependency interface IComponentContext which can be injected into any class that needs to do any resolution manually.
Update:
Here is a scenario. My controller uses a service who initialization depends upon the input parameter passed in the controller method and hence the dependency cannot be instantiated during construction time.
I understand that this is somewhat an anti pattern for DI, but it is requirement at few places and hence injecting the DI container is next best thing. Simple Injector samples should use of static variable to share the container which i want to avoid and also it is not possible by the way SimpleInjectorInitializer works.
Except for any code that is part of the startup path of the application, no code should depend directly on the container (or a container abstraction, container facade, etc). This pattern is called Service Locator and Mark Seemann has a good explanation why this is a bad idea.
So components (such as Controllers) should not depend on the container directly, since this hides the used dependencies and makes classes harder to test. Furthermore your code starts to depend on an external framework (making it harder to change) or depending on an abstraction it doesn't need to know about.
My controller uses a service who initialization depends upon the input
parameter passed in the controller method and hence the dependency
cannot be instantiated during construction time
There's a general pattern for this problem: the abstract factory design pattern. The factory pattern allows you to delay the creation of types and allows you to pass in extra runtime parameters for the construction of a certain type. When you do this, your controller doesn't have to depend on Container and it prevents you from having to pass in a constructed container in your unit tests (DI frameworks should in general not be used in your unit test projects).
Do note however that letting your components require runtime data during creation is a code smell. Prevent doing that.
You might think that by doing this we are just moving the problem to the factory implementation. Although we are moving the dependency on the container into the factory implementation, we are in fact solving the problem because the factory implementation will be part of the application's Composition Root, which allows the application code itself oblivious to any DI framework.
So this is how I advice you to structure your code:
// Definition of the factory in the UI or BL layer
public interface ISomeServiceFactory
{
ISomeService Create(int inputParameter);
}
// Controller depending on that factory:
public class MyController : Controller
{
private readonly ISomeServiceFactory factory;
public MyController(ISomeServiceFactory factory)
{
this.factory = factory;
}
public ActionResult Index(int value)
{
// here we use that factory
var service = this.factory.Create(value);
}
}
In your composition root (the start up path) we define the factory implementation and the registration for it:
private class SomeServiceFactory : ISomeServiceFactory
{
private readonly Container container;
// Here we depend on Container, which is fine, since
// we're inside the composition root. The rest of the
// application knows nothing about a DI framework.
public SomeServiceFactory(Container container)
{
this.container = container;
}
public ISomeService Create(int inputParameter)
{
// Do what ever we need to do here. For instance:
if (inputParameter == 0)
return this.container.GetInstance<Service1>();
else
return this.container.GetInstance<Service2>();
}
}
public static void Initialize()
{
var container = new Container();
container.RegisterSingle<ISomeServiceFactory, SomeServiceFactory>();
}
Upon creation, the Container registers itself (using the call RegisterSingle<Container>(this)) so you can always inject the container into any component. That's similar to injecting the IComponentContext when working with Autofac. But the same holds for Autofac, Simple Injector, and any other container: you don't want to inject your container into components that are located outside the composition root (and there hardly ever is a reason for it).

Inject EventAggregator into ViewModel with Caliburn Micro

Extracted from the Caliburn Micro documentation on EventAggregator:
// Creating the EventAggregator as a singleton.
public class Bootstrapper : BootstrapperBase {
private readonly SimpleContainer _container =
new SimpleContainer();
// ... Other Bootstrapper Config
protected override void Configure(){
_container.Singleton<IEventAggregator, EventAggregator>();
}
// ... Other Bootstrapper Config
}
// Acquiring the EventAggregator in a viewModel.
public class FooViewModel {
private readonly IEventAggregator _eventAggregator;
public FooViewModel(IEventAggregator eventAggregator) {
_eventAggregator = eventAggregator;
}
}
So the question is how do you get the instance of EA created by Bootstrapper to inject into your VM?
var svm = new SomeViewModel(?);
I tried using Caliburn.Micro.IoC.Get method but that didn't work...
No, you don't var svm = new SomeViewModel(?) and don't use IoC.Get because service location is becoming an anti-pattern.
The pattern suggested by the article author is best-practice, that is you should inject your dependencies to the objects that need them through constructor injection.
I don't know how to say it in any other way, but Make Your Application Composable and create an Architecture for you Presentation Layer.
I would check the Screens, Conductors and Composition article because it has some great ideas related to what i am saying and the application that accompanies it is a great one.
I would also read about dependency injection.
I wrote the article you are referencing. Sniffer is correct (please leave the green tick with him). Caliburn.Micro invests heavily in a concept called composition. What this means is that the whole object graph is constructed implicitly at run time, or composed, if you will.
The idea is that your "shell" ViewModel is created by the bootstrapper, the shell in turn creates other ViewModels and so on down the graph. This allows constructor injection to be used and provides the best composability.
However, there are times when this is not the desired functionality, for this we do provide a service locator by way of the IoC class; As Sniffer stated though, most use cases for service location are deemed to be anti patterns and as such it's usage should be severely scrutinized otherwise it will bite you on the ass down the road.
I am putting the finishing touches on two new articles for both IoC and our built in dependency container, SimpleContainer, once these are up I will add the relevant links to the EventAggregator docs which should provide more context around injection sites and best practice.

Categories

Resources