我有兴趣在我的项目中实现一个IoC容器,但是我还没有看到一个可以满足我需要的例子。
在这种情况下,我的应用程序是在WPF中构建的,并使用MVVM模式为红外视频格式创建播放器。在这种格式中,每个视频实际上由多个“子帧”组成(将其视为同时以多个快门速度捕获以增加数据的动态范围),每个子帧都显示在TabControl中。我想使用IoC容器来帮助我为每个选项卡创建ViewModel,但我有两个问题。
我需要一种方法来传递代表我正在创建ViewModel的子帧的对象,因此至少有一个ViewModel的依赖项不能由IoC容器创建,因为它已经存在。
我在视图中有用户控件,用于具有自己的ViewModel的子帧,因此这些ViewModel也需要由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中:
public SubframeViewModel(ISubframe subframe)
{
_subframe = subframe;
// FrameController tracks the current frame number and fires an event
// when it changes
var frameController = new FrameController(subframe);
// ImageViewModel represents the actual movie image. Uses FrameController
// to know when to raise PropertyChanged for the property that represents
// the image
ImageViewModel = new ImageViewModel(subframe, frameController);
// FrameControlViewModel represents the playback controls. Uses
// FrameController to implement actions
// Play, Pause, Jump to frame, Jump to time...
FrameControlViewModel = new FrameControlViewModel(subframe, frameController);
}
我希望在不更改现有语义的情况下获得
在开放电影代码中:
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;
}
实际上,涉及更多协调和ViewModel对象,但模式是相同的。也就是说,我想你可以在这里看到为什么我对IoC容器感兴趣。
我认为我的情景应该相当普遍,但我不确定,我不想浪费时间试图将方形钉子放入圆孔中,所以这是我的问题。任何/所有IoC容器都可以这样做吗?如果没有,你能否指出我将改进我的代码并使IoC工作的重构?
答案 0 :(得分:1)
Autofac绝对可以满足您的需求 - 显式提供的参数可以与容器自动装配的参数组合使用:
vm = container.Resolve<SubFrameViewModel>(new NamedParameter("subframe", subframe));
(也可以按类型而不是名称进行匹配。)
你甚至可以让容器将一个Func或自定义委托注入到调用组件中,这样就不需要容器依赖(即调用Resolve):
Func<ISubFrame, SubFrameViewModel> _vmFactory; // Injected
vm = _vmFactory(subframe);
有关后者的信息,请参阅http://code.google.com/p/autofac/wiki/DelegateFactories。
尼克
答案 1 :(得分: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解析器与其他VM配合的紧密耦合程度。如果您的imageVM和frameControlVMs需要自己的IoC,您可以简单地将它们链接在一起:
// 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);
}