SimpleIoc - can it provide new instance each time required?
Asked Answered
A

4

21

So far as I understand, SimpleIoc uses GetInstance method to retrieve an instance of a class that is registered. If the instance doesnt exist, it will create it. However, this instance is cached and always retrieved, which mimics the singleton pattern.

My thinking is that there is no need to keep an instance of ViewModel in a memory if there is a small possibility that this ViewModel will be needed twice, so I would like to create new instance of it each time that is needed. If we have are having a factory for ViewModels, we will have a property like this:

public MyViewMOdel MyViewModel
{
    get { return SimpleIoc.Default.GetInstance<MyViewModel>(); }
}

this one uses singleton pattern, which I think is not best practice in all cases. In order to circumvent this problem, I do this:

public MyViewModel MyViewModel
{
    get { return new MyViewModel(SimpleIoc.Default.GetInstance<ISomeInterface>()); }
}

This one has a disadvantage that if I ever change a constructor for MyViewModel, I will need to update this property also. Not big deal, but still there is some sort of dependency.

How do you handle this scenario, and is there something I am missing? and why it was decided not to have non-shared instance returned.

And another question is, in MVVM Deep dive session Laurent uses GetInstance method right after he registers a particular ViewModel, in order to, as he says, ensure that there is already an instance of this ViewModel in container. Why exactly is this necessary? If you are fetching a ViewModel through ViewModelLocator, then you will create it whenever required. So why would I want to have them created upfront?

Ascomycete answered 18/2, 2012 at 15:2 Comment(0)
G
10

You can get a different instance each time by passing a different key to the GetInstance method. However the instances will be cached, so if you do not want to keep them in the cache, you will need to call Unregister with the corresponding key.

In the demo, I was creating the VM upfront because the MainVM was sending messages to the SecondaryVM. Since the registration to the Messenger is done in the SecondaryVm's constructor, it needs to be created before it can start receiving messages. The Messenger is great because it is very decoupled, but it is one of these cases where you need to do extra work to compensate the decoupling: The SecondaryVM is the target of messages even though the MainVM does not get any reference to it.

Hope it makes sense. Cheers, Laurent

Glandular answered 19/2, 2012 at 16:27 Comment(2)
Hi, Laurent, in the case of non-shared instance it doesn't matter if you are using keys or not (I assume that we do not have multiple instances of the same view at the same time). In both cases I would need to register / unregister a viewmodel, so I would need to keep track about them. I think it would still be a simple Ioc if there was a Register option for shared and non-shared instances. I guess it would just require not to add created instance in container?Ascomycete
Your solution only works if constructor injection is not being used (which is not a good thing). In case the container takes the responsibility of injecting the dependencies, there is no way to tell it to create new instances and inject those into the constructor, is there? I am trying to avoid calling SimpleIoC.GetInstance() in my code as depending on the container is bad practice. How do I tell SimpleIoC to always create new instances and inject them instead of caching one instance? Seems to me a simple "cache" flag in SimpleIoC.Register would suffice.Livraison
L
4

After wrestling with SimpleIoC to provide new instances each time a specific type is requested and finding out this feature is not implemented (the key-based method accepted above doesn't fit scenarios where you want to say, perform a database operation and throw the connection away each time), I came up with a relatively decent solution combining IoC with the Factory pattern: Create a class that takes the responsibility of instantiating new instances of a certain type through a function:

class MyObjectFactory: IMyObjectFactory
{
    public MyObject CreateObject()
    {
        return new MyObject();
    }
}

Create the interface for MyObject factory class:

public interface IMyObjectFactory
{
    MyObject CreateObject();
}

Then configure the IoC container to provide the factory to any classes that use instances of MyObject:

SimpleIoc.Default.Register<IMyObjectFactory, MyObjectFactory>();

Now any class requiring a new instance of MyObject would declare its MyObjectFactory requirement (instead of MyObject requirement) in the constructor for constructor injection:

public class MyObjectUser
{
    MyObject _myObject;
    public MyObjectUser(IMyObjectFactory factory)
    {
        _myObject = factory.CreateObject();
    }
}

This way I think you're not bound by the limitations of the Factory pattern and have all the benefits of IoC containers and Constructor Injection, circumventing SimpleIoC's limitation as well.

Livraison answered 5/4, 2017 at 11:43 Comment(0)
M
3

SimpleIOC is what it is ... a simple IOC container. It will have some shortcommings ... but you are not bound to it you could always use another ICO container (e.g. Unity, Autofac, Castle, ...).

As Laurent states he modelled his SimpleIOC on this container. He also mentions this container as a source of his inspiration.

However, remember you are not bound to use a secific container with MVVM. In several of my projects I used Unity, but every other IOC container will to equally well, it is a matter of requirements, customer preferences, and - if everything else fails - plain old personal gusto.

Men answered 18/2, 2012 at 16:56 Comment(1)
Hi Obalix, I am aware that I can use another container, but since I am using MVVM light, I would not want to introduce another dll to load, if I do not need advanced features that unity (or any other IoC) offers. My thinking here is that this is not an advanced feature, that it doesn't involve too much coding to implement it, and that it is a feature that is going to be frequently used. I was also interested in finding out how other programmers that use SimpleIoc handle the requirements for non-shared instances of a viewmodel.Ascomycete
I
0

After reading all, very educational and high-quality answers in this thread I only would like to point something maybe not so advanced technologically but I think quite important to be placed in the thread about customizing IoC Container: I think that writing you own IoC Container is one of the easiest my-own-libraries-related task in OOP and I am pretty sure valuable educationally. I don't put any tutorials here because hopefully everybody that read my opinion knows Google Search or tools alike ;-)

Illyrian answered 14/9, 2020 at 1:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.