1

我正在尝试从 MainViewModel 实例化 SecondViewModel 注入第二个参数,这些参数是在 IoCContainer 中注册的服务和来自 MainVM 的对象。

代码是这样的:

class MainViewModel
{
    public MainViewModel()
    {
    }

    private string message = "the message";
    public string Message { get; set; }
}

class SecondViewModel
{
    public SecondViewModel(IService service, string message)
    {
    }
}

现在,我知道我可以让 IoC Container 将 SecondViewModelFactory(承载服务实例)注入 MainViewModel,因此它可以通过它创建 SVM,但是如果 IService 的实现非常繁重,我不想实例化它,但当我真的需要它时。

如果我必须以类似的方式实例化其他 ViewModel 怎么办?我是否必须创建大量 VMFactories 和构造函数的参数?

如果我使用通用 ViewModelFactory,则需要实例化它,传递我拥有的每个 ViewModel 所需的所有服务,无论它们是否会被创建。

你知道我的案子有什么更好的解决方案吗?

4

2 回答 2

2

一般来说,服务的创建不应该很重。他们的构造函数应该只存储传入的依赖项。如果它在后台使用了一些繁重的资源,则不应通过构造函数访问它们。这使构造函数保持简单(避免您必须对其进行测试)并允许非常快速地组合对象图。

如果真的没有办法解决这个问题,基本上有两种模式可以应用:

1. 工厂

您可以注入工厂来延迟类型的创建。当创建应该明确控制的对象(例如,应该尽快释放的实例)时,工厂也很有用。有几种创建工厂的方法。有些人喜欢在他们的服务中注入Func<T>Lazy<T>依赖,但我觉得这太含蓄了。我宁愿注入一个ISomeServiceFactory,因为我发现这更具可读性。缺点是您需要为此定义一个新接口。但是,如果您发现自己有许多工厂接口,那么您的设计可能无论如何都存在问题。

2. 代理

您可以将服务隐藏在代理后面,而不是创建工厂。该代理可以实现与服务相同的接口,并将为您执行延迟。这可以防止您让应用程序依赖于不同的接口(一个IServiceFactoryLazy<T>例如)。尤其是Lazy<T>将有关创建的详细信息泄露给此类依赖项的使用者。如果方便的话,您仍然可以将 aLazy<T>注入此代理。这不是问题。该代理通常是您的组合根的一部分,您的应用程序的其余部分仍将取决于您的IService而不是您的Lazy<IService>.

Please be aware that the use of factories, proxies and lazy initiation does complicate the wiring of the container. So don't use if unless you measured that you really need it. They complicate things, because of the indirection, which makes it harder to follow interlectually. And they make it harder to verify your configuration using automated tests. For more information about verifying your container, take a look here and here.

于 2012-09-17T10:04:44.690 回答
1

大多数IoC Containers支持延迟依赖,Lazy<>以避免立即创建昂贵的类。

因此,在您的代码中,您可以为昂贵的 IService 做一些懒惰:

class SecondViewModel
{
    public SecondViewModel(Lazy<IService> service, string message)
    {
    }
}

您可以使用一些流行的 IoC 容器并查看它们如何支持延迟加载:AutofacNInject

于 2012-09-14T13:26:05.097 回答