How to Use Mvvmlight Simpleioc

how to use MVVMLight SimpleIoc?

SimpleIoc crib sheet:

1) You register all your interfaces and objects in the ViewModelLocator

class ViewModelLocator 
{
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<SecondViewModel>();
}

public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
}

2) Every object is a singleton by default. To resolve an object so that it's not a singleton you need to pass a unique value to the GetInstance call:

SimpleIoc.Default.GetInstance<MainViewModel>(Guid.NewGuid().ToString());

3) To register a class against an interface:

SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();  

4) To register a concrete object against an interface:

SimpleIoc.Default.Register<IDataService>(myObject);     

5) To register a concrete type:

SimpleIoc.Default.Register<MainViewModel>();   

6) To resolve an object from an interface:

SimpleIoc.Default.GetInstance<IDataService>();

7) To resolve an object directly (does buildup and dependency resolution):

SimpleIoc.Default.GetInstance<MainViewModel>();

8) MVVM makes doing design-time data really easy:

if (ViewModelBase.IsInDesignModeStatic) 
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}

If you're in design-time mode it will automatically register your design-time services, making it really easy to have data in your viewmodels and views when working in the VS designer.

Hope this helps.

SimpleIOC with MVVMlight register and use

The UnitOfWorkItem property is looking for the registered UnitOfWork. But you never register anything with that class, you register the IUnitOfWork!

You need to fix your UnitOfWorkItem by changing UnitOfWork into IUnitOfWork:

public UnitOfWork UnitOfWorkItem
{
get
{
return ServiceLocator.Current.GetInstance<IUnitOfWork>();
}
}

Even better:

Just for your information, the power of an IoC container is that you can chain the registration. For example, in your case, your LoginViewModel and your MainViewModel require a UnitOfWork as constructor parameter.

If you register both UnitOfWork, MainViewModel and LoginViewModel like this:

SimpleIoc.Default.Register<UnitOfWork>(); 
SimpleIoc.Default.Register<LoginViewModel>();
SimpleIoc.Default.Register<MainViewModel>();

The container will automatically provide to the ViewModels constructor the registred UnitOfWork and so on.

This way you do not need to create a property getting the UnitOfWork for giving it to the LoginViewModel constructor.

MVVM Light SimpleIoc

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);
}

MVVM Light SimpleIoC can't find instance

I forget how you'd register connectionstring but I think what your error is saying is that the constructor of deviceaccesservice:

public DeviceDataAccessService(string connectionString) 

Expects a connection string as a parameter.
It doesn't have that to give it so...crash.
I think you need something more like:

SimpleIoc.Default.Register<IDeviceDataAccessService>(() => {
return new DeviceDataAccessService("Whatever connectionstring should be");
});

How to use MvvmLight SimpleIoc in different project

This is a bit of a guess, but here goes....

The link between the ViewModelLocator and the View is in the XAML file, usually via a Static resource. Here's the definition of that resource e from one of my projects:

 <Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:Rcl.Reports.DataModelManager.ViewModel" />
</Application.Resources>

Nore the full namespace path to the ViewModelLocator is required. When MVVM installs itself it generates this, and assumes that the ViewModelLocator will be in the main WPF project you've installed it in (and in which you need to install it, as the project will be directly be using MVVMLight).

If you have the wrong namespace, not the one of your library, then WPF can't find it and will silently do nothing.

Check that the namespace is defined correctly and see what happens.

Mvvm light SimpleIoC in usercontrol


How would I best accomplish that when the default IoC container seems to be a static object?

Don't use the default container but create your own instance of the SimpleIoc class:

User Control A:

SimpleIoc containerA = new SimpleIoc();
containerA.Register<ViewModel>();
...
ViewModel vm = containerA.GetInstance<ViewModel46>();

User Control B:

SimpleIoc containerB = new SimpleIoc();
...

mvvm light simpleIoc constructor injection

Don't map the IList interface, use a factory for your ShowEmployeeViewModel class:

SimpleIoc.Default.Register(() => new ShowEmployeeViewModel(new List<IEmployee>()));

MVVM Light SimpleIoc Unregister instance failed


The question: How to release the instance?

If you register the type like this:

SimpleIoc.Default.Register<CollectorViewModel>();

...you unregister it like this, i.e without any key:

SimpleIoc.Default.Unregister<CollectorViewModel>();

This works as expected:

ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

SimpleIoc.Default.Register<CollectorViewModel>();
Debug.Assert(SimpleIoc.Default.GetAllInstances<CollectorViewModel>().Count() == 1);
SimpleIoc.Default.Unregister<CollectorViewModel>();
Debug.Assert(SimpleIoc.Default.GetAllInstances<CollectorViewModel>().Count() == 0);

If you get an instance with a key like this:

var instance = ServiceLocator.Current.GetInstance<CollectorViewModel>("xyz");

...you unregister this instance like this:

SimpleIoc.Default.Unregister<CollectorViewModel>("xyz");

This also works as expected:

ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

SimpleIoc.Default.Register<CollectorViewModel>();
Debug.Assert(SimpleIoc.Default.GetAllInstances<CollectorViewModel>().Count() == 1);
var instance = ServiceLocator.Current.GetInstance<CollectorViewModel>("xyz");
Debug.Assert(SimpleIoc.Default.GetAllInstances<CollectorViewModel>().Count() ==2);
SimpleIoc.Default.Unregister<CollectorViewModel>("xyz");
Debug.Assert(SimpleIoc.Default.GetAllInstances<CollectorViewModel>().Count() == 1);

How to persist a single business object with MVVM-Light SimpleIoc

As it states in the linked tutorial

2) Every object is a singleton by default. To resolve an object so that it's not a singleton you need to pass a unique value to the GetInstance call:

SimpleIoc.Default.GetInstance<MainViewModel>(Guid.NewGuid().ToString());

So to get the same instance each time you pass nothing (or always the same value) to the call to GetInstance

[Test]
public void CreateNonGeneric_ReturnsSameInstance1()
{
SimpleIoc.Default.Register<Repository>();

var result1 = SimpleIoc.Default.GetInstance<Repository>();
var result2 = SimpleIoc.Default.GetInstance<Repository>();

Assert.That(result1, Is.SameAs(result2));
}

[Test]
public void CreateNonGeneric_ReturnsSameInstance2()
{
SimpleIoc.Default.Register<IRepository, Repository>();

var result1 = SimpleIoc.Default.GetInstance<IRepository>();
var result2 = SimpleIoc.Default.GetInstance<IRepository>();

Assert.That(result1, Is.SameAs(result2));
}

[Test]
public void CreateNonGeneric_ReturnsSameInstance3()
{
SimpleIoc.Default.Register<Repository>();

var result1 = SimpleIoc.Default.GetInstance<Repository>("alwaysthesame");
var result2 = SimpleIoc.Default.GetInstance<Repository>("alwaysthesame");

Assert.That(result1, Is.SameAs(result2));
}

UPDATE

You can configure the dependencies during the registration. Here's one with a string

[Test]
public void RegisterSingletonWithFunc_GetIstance_ReturnsSameInstanceEachTime()
{
SimpleIoc.Default.Register<IRepository, Repository>();
SimpleIoc.Default.Register<Repository>(() =>
new Repository("dependency"), "single");
var result1 = SimpleIoc.Default.GetInstance<IRepository>("single");
var result2 = SimpleIoc.Default.GetInstance<IRepository>("single");

Assert.That(result1, Is.SameAs(result2));
}

And here's one with a dependency that is created by SimpleIoc

[Test]
public void RegisterSingletonWithDependentClass_GetIstance_ReturnsSame()
{
SimpleIoc.Default.Register<IRepository, Repository>();
SimpleIoc.Default.Register<SomeService>();
SimpleIoc.Default.Register<Repository>(() =>
new Repository(
SimpleIoc.Default.GetInstance<SomeService>())
, "single");
var result1 = SimpleIoc.Default.GetInstance<IRepository>("single");
var result2 = SimpleIoc.Default.GetInstance<IRepository>("single");

Assert.That(result1, Is.SameAs(result2));
}


Related Topics



Leave a reply



Submit