SimpleIoc - 它能够每次需要时提供新的实例吗?

21
据我了解,SimpleIoc使用GetInstance方法获取已注册类的实例。如果该实例不存在,则会创建它。但是,此实例被缓存并始终检索,这类似于单例模式。
如果存在一个小概率情况下不需要在内存中保留ViewModel的实例,那么每次需要时都可以创建一个新的实例。如果我们拥有ViewModel的工厂,我们将拥有以下属性:
public MyViewMOdel MyViewModel
{
    get { return SimpleIoc.Default.GetInstance<MyViewModel>(); }
}

这个代码使用了单例模式,但我认为在某些情况下这并不是最佳实践。为了解决这个问题,我做了以下操作:

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

这种方法的劣势在于,如果我修改了 MyViewModel 的构造函数,那么我还需要更新这个属性。虽然不是什么大问题,但还是存在某种依赖关系。

你是如何处理这种情况的?我是否漏掉了什么?为什么决定不返回非共享实例?

另外一个问题是,在 MVVM 深入探讨中,Laurent 在注册特定的 ViewModel 后使用 GetInstance 方法,以确保容器中已经有此 ViewModel 的实例。为什么会有这种必要性呢?如果通过 ViewModelLocator 获取 ViewModel,则会在需要时创建它。那么我为什么想要预先创建它们呢?

4个回答

10

通过向GetInstance方法传递不同的键,可以每次获取不同的实例。但是这些实例将被缓存,因此如果您不想将它们保留在缓存中,则需要使用相应的键调用Unregister。

在演示中,我提前创建了VM,因为MainVM正在向SecondaryVM发送消息。由于在SecondaryVm的构造函数中注册到Messenger,因此它需要在开始接收消息之前被创建。Messenger非常解耦,但这是其中一种需要做额外工作来弥补解耦的情况:即使MainVM没有任何对此的引用,SecondaryVM也是消息的目标。

希望这有意义。 谢谢, Laurent


嗨,劳伦特,在非共享实例的情况下,无论您是否使用键都没有关系(我假设我们在同一时间没有多个相同视图的实例)。在这两种情况下,我都需要注册/注销视图模型,因此我需要跟踪它们。如果有一个用于共享和非共享实例的注册选项,那么我认为它仍然是一个简单的Ioc。我猜只需要不将已创建的实例添加到容器中? - Goran
4
只有在未使用构造函数注入的情况下(这不是一件好事),您的解决方案才有效。如果容器负责注入依赖项,则无法告诉它创建新实例并将其注入构造函数,对吗?我试图避免在我的代码中调用SimpleIoC.GetInstance(),因为依赖于容器是不好的做法。如何告诉SimpleIoC始终创建新实例并注入它们,而不是缓存一个实例?在SimpleIoC.Register中似乎只需要一个简单的“缓存”标志即可。 - TheAgent

4

在与SimpleIoC搏斗,试图提供每次请求特定类型时都生成新实例的功能后,发现该功能未被实现(上面接受的基于键的方法不适用于您想要执行数据库操作并每次都丢弃连接的情况),我想到了一个相对不错的解决方案,将IoC与工厂模式结合起来:

创建一个类,通过函数负责实例化某种类型的新实例:

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

SimpleIOC是一个简单的IOC容器。它可能有一些缺点,但你并不受其限制,你可以使用其他的IOC容器(例如:Unity、Autofac、Castle等)。

正如Laurent所说,他的SimpleIOC是基于这个容器进行建模的。他还提到这个容器是他灵感的来源之一。

然而,请记住你不必使用特定的容器来实现MVVM。在我的几个项目中,我使用了Unity,但任何其他的IOC容器同样适用,这取决于需求、客户偏好以及最后的个人喜好。


1
嗨Obalix,我知道我可以使用另一个容器,但由于我正在使用MVVM light,如果我不需要Unity(或任何其他IoC)提供的高级功能,我不想引入另一个dll来加载。我的想法是这不是一项高级功能,它不涉及太多编码来实现它,并且这是一个经常使用的功能。我还想了解其他使用SimpleIoc的程序员如何处理视图模型的非共享实例要求。 - Goran

0

在阅读了这个帖子中所有非常有教育意义和高质量的答案之后,我只想指出一些可能不那么先进技术上但我认为在关于自定义 IoC容器 的帖子中相当重要的事情:我认为编写自己的 IoC容器 是面向对象编程中最容易的自己编写库相关任务之一,而且我非常确定它具有很高的教育价值。我没有在这里放任何教程,因为希望每个阅读我的观点的人都知道 Google搜索 或类似的工具 ;-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接