SimpleIoc - 它是否可以在每次需要时提供新实例?

时间:2012-02-18 15:02:10

标签: c#-4.0 mvvm mvvm-light silverlight-5.0

据我所知,SimpleIoc使用GetInstance方法来检索已注册的类的实例。如果实例不存在,它将创建它。但是,此实例被缓存并始终检索,这模仿单例模式。

我的想法是,如果只需要两次ViewModel的可能性很小,就不需要在内存中保留ViewModel的实例,所以我想在每次需要时创建它的新实例。如果我们有ViewModel工厂,我们将拥有这样的属性:

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

这个使用单例模式,我认为在所有情况下都不是最佳实践。为了避免这个问题,我这样做:

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

这个缺点是,如果我更改MyViewModel的构造函数,我还需要更新此属性。没什么大不了的,但仍然存在某种依赖性。

你如何处理这种情况,是否有我遗漏的东西?以及为什么决定不返回非共享实例。

另一个问题是,在MVVM Deep dive会话中,Laurent在注册特定的ViewModel之后立即使用GetInstance方法,正如他所说的那样,确保容器中已存在此ViewModel的实例。为什么这有必要?如果您通过ViewModelLocator获取ViewModel,那么您将在需要时创建它。那么我为什么要提前创建它们呢?

4 个答案:

答案 0 :(得分:9)

每次都可以通过将不同的密钥传递给GetInstance方法来获取不同的实例。但是,实例将被缓存,因此如果您不想将它们保留在缓存中,则需要使用相应的密钥调用取消注册。

在演示中,我提前创建了VM,因为MainVM正在向SecondaryVM发送消息。由于Messenger的注册是在SecondaryVm的构造函数中完成的,因此需要先创建它才能开始接收消息。 Messenger很棒,因为它非常分离,但是在这些情况下你需要做额外的工作来补偿解耦:即使MainVM没有得到任何引用,SecondaryVM也是消息的目标。

希望它有意义。 干杯, 劳伦

答案 1 :(得分:2)

SimpleIOC就是它......一个简单的IOC容器。它会有一些缺点......但是你并没有受到约束,你可以随时使用另一个ICO容器(例如Unity,Autofac,Castle,......)。

作为Laurent states,他在this container上建模了他的SimpleIOC。他还提到this container是他灵感的来源。

但是,请记住您不必使用具有MVVM的分区容器。在我的几个项目中,我使用了Unity,但是其他每个IOC容器都同样适用,这是需求,客户偏好的问题,并且 - 如果其他一切都失败了 - 简单的个人热情。

答案 2 :(得分:2)

在与SimpleIoC进行搏斗之后,每次请求特定类型时都会提供新实例,并且未实现此功能(上面接受的基于密钥的方法不适合您想要说明的情况,执行数据库操作和每次抛出连接),我想出了一个相对不错的解决方案,将IoC与Factory模式相结合: 创建一个类,负责通过函数实例化某个类型的新实例:

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

为MyObject工厂类创建接口:

public interface IMyObjectFactory
{
    MyObject CreateObject();
}

然后配置IoC容器以向使用MyObject实例的任何类提供工厂

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

现在任何需要MyObject新实例的类都会在构造函数注入的构造函数中声明其MyObjectFactory需求(而不是MyObject需求):

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

通过这种方式,我认为您不受工厂模式的限制,并且具有IoC容器和构造函数注入的所有优点,也可以避开SimpleIoC的限制。

答案 3 :(得分:0)

在阅读了该主题的所有非常有教育意义和高质量的答案之后,我只想指出一些技术上可能不那么先进的东西,但是我认为放置在定制IoC Container的主题中非常重要:我认为编写自己的IoC容器是OOP中最简单的与我自己的图书馆相关的任务之一,我相信在教育上非常有价值。我没有在这里放置任何教程,因为希望每个读过我观点的人都知道Google Search或类似的工具;-)