使用IoC将参数从ViewModel传递到另一个

时间:2012-09-14 11:45:47

标签: c# .net mvvm inversion-of-control ioc-container

我正在尝试从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所需的所有服务,无论它们是否会被创建。

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

2 个答案:

答案 0 :(得分:2)

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

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

<强> 1。工厂

您可以注入工厂以延迟创建类型。当创建应明确控制的对象(例如,应尽快处理的实例)时,工厂也很有用。有几种创建工厂的方法。有些人喜欢在他们的服务中注入Func<T>Lazy<T>个依赖关系,但我发现这太隐含了。我宁愿注入一个ISomeServiceFactory,因为我发现它更具可读性。缺点是你需要为此定义一个新的界面。但是,如果您发现自己拥有许多工厂接口,那么无论如何您可能都有problem in your design

<强> 2。代理

您可以隐藏代理服务器,而不是创建工厂。此代理可以实现与服务相同的接口,并将为您执行延迟执行。这可以防止您让应用程序依赖于不同的接口(例如IServiceFactoryLazy<T>)。特别是Lazy<T>泄漏了有关向这种依赖的消费者创造的细节。如果方便,您仍然可以向此代理注入Lazy<T>。那不是问题。该代理通常会成为您composition root的一部分,而您的应用程序的其余部分仍将取决于您的IService,而不是您的Lazy<IService>

请注意,使用工厂,代理和延迟启动会使容器的布线复杂化。所以除非你测量到你真的需要它,否则不要使用它。由于间接性,它们使事情复杂化,这使得更难以间接地遵循。而且它们使用自动化测试更难以验证您的配置。有关验证容器的详细信息,请查看herehere

答案 1 :(得分:1)

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

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

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

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