2009-11-19 86 views
0

我有兴趣在我的项目中实现一个IoC容器,但我还没有看到一个能够满足我需要的示例。IoC容器对象范围

下面是情况,我的应用程序是在WPF中构建的,并使用MVVM模式为红外视频格式创建播放器。在这种格式下,每个视频实际上由多个“子帧”组成(将其视为以多个快门速度同时捕捉,以增加数据的动态范围),每个视频都显示在TabControl中。我想使用IoC容器来帮助我为每个选项卡创建ViewModels,但我有两个问题。

  1. 我需要一种方法在表示子我创建一个视图模型为不能由IoC容器创建,因为它已经存在的视图模型的依赖,这样至少一个对象来传递。

  2. 我有视图内的用户控件有自己的ViewModels子视图,所以这些ViewModels也需要由IoC容器创建。这个问题是,尽管控件(和它们的ViewModel)具有不同的关注点,但它们并不完全独立,因此它们使用了一些协调对象。不幸的是,在我见过的所有示例中,您可以让IoC容器创建一个新的依赖项实例或具有一个单例,但我需要的是在创建子视图模型期间受控范围内的单个实例ViewModel 。

这是很多文字,所以这里是一些代码,显示我在做什么,我想做什么。

我现在

有什么在打开电影代码:

foreach (var subframe in movieFile) 
{ 
    // Subframes is the ObservableCollection that the TabControl is bound to 
    Subframes.Add(new SubframeViewModel(subframe)); 
} 

在SubframeViewModel:

我想有在不改变现有sematics

在打开电影代码:

foreach (var subframe in movieFile) 
{ 
    Subframes.Add(container.Resolve<SubframeViewModel>()); 
} 

在SubframeViewModel:

public SubframeViewModel(ISubframe subframe, ImageViewModel imageModel, 
          FrameControlViewModel frameModel) 
{ 
    _subframe = subframe; 

    ImageViewModel = imageModel; 

    FrameControlViewModel = frameModel; 
} 

在现实中,也有更多的协调和视图模型对象参与,但图案是相同的。这就是说,我认为你可以看到为什么我对这里的IoC容器感兴趣。

我认为我的场景应该是相当常见的,但我不确定,我不想浪费我的时间,试图将一个方形的钉子插入圆孔,所以这里是我的问题。任何/所有的IoC容器可以做到这一点吗?如果没有,你可以指向我的重构,这将改善我的代码,并使IoC工作?

回答

1

Autofac肯定做您所需要的 - 明确规定参数可与由容器自动装配组合:

vm = container.Resolve<SubFrameViewModel>(new NamedParameter("subframe", subframe)); 

(按类型而不是名称匹配也是可能的。)

你甚至可以有容器注入Func键或自定义委托到调用组件,使容器的依赖(即调用解决)是不必要的:

Func<ISubFrame, SubFrameViewModel> _vmFactory; // Injected 
vm = _vmFactory(subframe); 

有关信息见http://code.google.com/p/autofac/wiki/DelegateFactories后者。

尼克

+0

嗯会误解你的问题在二读 - 反正HTH! – 2009-11-19 21:13:07

+0

无论这是否完全回答了我的所有问题,现在我指出了正确的方向。我可以肯定地看到,我可以如何使这一切更干净地工作。谢谢您的帮助。 – 2009-11-20 14:03:48

+0

看着Autofac文档,它看起来像我是否为每个子帧创建了一个嵌套容器并将FrameController标记为ContainerScoped,我所需要做的就是使用您在那里指定子帧并满足所有需求。这似乎是一个合理的事情吗? – 2009-11-20 14:13:43

1

它看起来像你想处理您的IoC方案的额外构造函数的参数,我看到两个选项:

1 - 创建一个简单的构造这需要在一个子帧,并且暴露ImageViewModel和FrameControlViewModel公众可设置的属性,像这样:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe); 
    subframeVM.ImageVM = imageVM; 
    subframeVM.FrameControlVM = frameControlVM ; 
    Subframes.Add(subframeVM); 
} 

2 - 传给你需要到IoC容器,它只是传递参数到SubframeVM构造函数中的参数:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe, imageVM, frameControlVM); 
    Subframes.Add(subframeVM); 
} 

最终您选择哪一个取决于您希望您的SubframeViewModel IoC解析器与其他虚拟机的紧密耦合程度。如果您imageVM和frameControlVMs需要自己的国际石油公司,你可以简单地把它们连在一起:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var frameControlVM = container.Resolve<FrameControlViewModel >(subframe); 
    var imageVM = container.Resolve<ImageViewModel>(subframe, frameControlVM); 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe, imageVM, frameControlVM); 
    Subframes.Add(subframeVM); 
} 
+0

谢谢Micah,这真的有帮助。你在这里使用哪个IoC容器? – 2009-11-20 14:05:01

+0

我不知道。 :) 几年前,当我需要做动态程序集加载以及工厂风格的类实例化时,我推出了自定义程序。但是,对于我所做的大多数小型项目来说,通过外部配置实现可插入实例的好处对于我来说比编译时检查更有价值 - 而且我不喜欢提前在接口和抽象类中进行猜测;这是我为重构保存的东西。 – micahtan 2009-11-21 00:34:52