代码之家  ›  专栏  ›  技术社区  ›  Jammin

Silverlight构造函数注入视图模型+设计模式

  •  10
  • Jammin  · 技术社区  · 15 年前

    我正在尝试在Silverlight4中编写可测试的视图模型。我目前正在使用MVVM灯。

    我正在使用autopac,ioccontainer的工作做得很好。但是,要将绑定到视图的ViewModel的构造函数注入,我有这个构造函数链接:

        public UserViewModel() : this(IoCContainer.Resolve<IUserServiceAsync>())
        {
    
        }
    
        public UserViewModel(IUserServiceAsync userService) 
        {
            if (this.IsInDesignMode) return;
    
            _userService = userService;
        }
    

    感觉不干净,但这是迄今为止我找到的最佳选择。这是可行的,我的应用程序可以按需要工作,并且可以在控制反转的情况下进行测试。

    但是,当我的虚拟机绑定到我的视图时,如下所示:

     <UserControl.DataContext>
                <ViewModel:UserViewModel />
     </UserControl.DataContext>
    

    在我的XAML页面属性中,VS2010和Blend中的设计模式都不起作用。

    有没有更好的方法来实现我在Silverlight中尝试的设计模式?失败的设计模式不是一个交易破坏者,但在学习XAML时会很方便。不过,一条干净的没有链子的路还是不错的!

    我想也许可以使用autopac/ioc将视图模型解析为视图,就像上面的xaml标记方法一样,然后沿着这条路线走?

    谢谢。

    1 回复  |  直到 15 年前
        1
  •  10
  •   Murven    15 年前

    我建议您不要实现第一个构造函数,而是实现一个ViewModelLocator,如下所示:

    public class ViewModelLocator
    {
    
        IoCContainer Container { get; set; }
    
        public IUserViewModel UserViewModel
        {
            get
            {
                return IoCContainer.Resolve<IUserViewModel>();
            }
        }
    
    }
    

    然后在XAML中,将定位器声明为静态资源:

    <local:ViewModelLocator x:Key="ViewModelLocator"/>
    

    初始化应用程序时,需要向定位器提供容器的实例:

    var viewModelLocator = Application.Current.Resources["ViewModelLocator"] as ViewModelLocator;
    if(viewModelLocator == null) { // throw exception here }
    viewModelLocator.Container = IoCContainer;
    

    然后,在XAML中,可以干净地使用资源:

    <UserControl
        DataContext="{Binding Path=UserViewModel, Source={StaticResource ViewModelLocator}}"
        />
        <!-- The other user control properties -->
    

    在设计阶段,可以实现MockViewModelLocator:

    public class MockViewModelLocator
    {
    
        public IUserViewModel UserViewModel
        {
            get
            {
                return new MockUserViewModel();
            }
        }
    
    }
    

    在XAML中适当地声明它:

    <local:MockViewModelLocator x:Key="MockViewModelLocator"/>
    

    最后在用户控件中使用它:

    <UserControl
        d:DataContext="{Binding Path=UserViewModel, Source={StaticResource MockViewModelLocator}}"
        DataContext="{Binding Path=UserViewModel, Source={StaticResource ViewModelLocator}}"
        />
        <!-- The other user control properties -->
    

    您可以使您的模拟视图模型定位器返回安全易读的数据供混合使用,并且在运行时您将使用真正的服务。

    这样就不会丢失设计时数据,也不必牺牲视图模型中依赖注入方法的清洁度。

    我希望这有帮助。