代码之家  ›  专栏  ›  技术社区  ›  Jon Norton

IoC容器对象作用域

  •  0
  • Jon Norton  · 技术社区  · 16 年前

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

    1. 我需要一种方法传入表示要为其创建ViewModel的子帧的对象,这样至少有一个ViewModel的依赖项不能由IoC容器创建,因为它已经存在。

    2. 我在视图中有一个子帧的用户控件,该子帧有自己的视图模型,因此这些视图模型也需要由IoC容器创建。问题在于,虽然控件(及其视图模型)有单独的关注点,但它们并不完全独立,因此它们使用一些协调对象。不幸的是,在我看到的所有示例中,您可以让IoC容器创建依赖项的新实例,也可以创建单实例,但我需要的是在创建子帧ViewModel时的受控时间范围内创建单个实例。

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

    我现在拥有的

    打开电影代码:

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

    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>());
    }
    

    在子帧视图模型中:

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

    实际上,涉及到更多的协调和ViewModel对象,但模式是相同的。也就是说,我想你可以理解为什么我对这里的国际奥委会集装箱感兴趣。

    我认为我的情况应该是相当普遍的,但我不确定,我不想浪费我的时间试图把一个正方形的钉入一个圆孔,所以这里是我的问题。任何/所有IoC容器都能做到这一点吗?如果不是,你能给我指一个能改进我的代码并使IoC工作的重构吗?

    2 回复  |  直到 16 年前
        1
  •  1
  •   Nicholas Blumhardt    16 年前

    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 关于后者的信息。

    尼克

        2
  •  1
  •   micahtan    16 年前

    看起来您想在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容器中,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);
    }
    

    最终选择哪一个取决于您希望子帧视图模型IoC解析器与其余vm的紧密耦合程度。如果您的imageVM和framecontrolvm需要它们自己的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);
    }