【问题标题】:Silverlight Constructor Injection into View Model + Design Mode视图模型+设计模式中的 Silverlight 构造函数注入
【发布时间】:2011-05-01 07:42:48
【问题描述】:

我正在尝试在 Silverlight 4 中编写可测试的 ViewModel。我目前正在使用 MVVM light。

我正在使用 AutoFac,而 IoCContainer 工作正常。但是要注入绑定到 Views 的 ViewModels 的构造函数中,我有这个构造函数链接:

    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 时会很方便。不过,更清洁的无连锁方式会很好!

我认为也许可以使用 AutoFac / IoC 将视图模型解析为视图,与上面的 XAML 标记方法相反,然后沿着这条路线走下去?

谢谢。

【问题讨论】:

    标签: c# silverlight silverlight-4.0 ioc-container mvvm-light


    【解决方案1】:

    我建议你实现一个 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 -->
    

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

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

    我希望这会有所帮助。

    【讨论】:

    • 感谢详细的回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2014-10-12
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多