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

Jam*_*min 10 c# silverlight ioc-container silverlight-4.0 mvvm-light

我试图在Silverlight 4中编写可测试的ViewModel.我正在使用MVVM灯.

我正在使用AutoFac和IoCContainer正在完成它的工作.但是要注入ViewModel的构造函数,它绑定到Views我有这个构造函数链接:

    public UserViewModel() : this(IoCContainer.Resolve<IUserServiceAsync>())
    {

    }

    public UserViewModel(IUserServiceAsync userService) 
    {
        if (this.IsInDesignMode) return;

        _userService = userService;
    }
Run Code Online (Sandbox Code Playgroud)

哪个不干净,但是到目前为止我找到的最佳选择.这是有效的,我的应用程序可以根据需要工作,并且可以通过控制倒置来测试

但是,我的VM绑定到我的视图,如下所示:

 <UserControl.DataContext>
            <ViewModel:UserViewModel />
 </UserControl.DataContext>
Run Code Online (Sandbox Code Playgroud)

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

是否有更好的方法来实现我在Silverlight中尝试仍然适用于设计模式的东西?丢失设计模式不是一个交易破坏者,但在学习XAML时会很方便.一个更干净的无链接方式会很好!

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

谢谢.

Mur*_*ven 10

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

public class ViewModelLocator
{

    IoCContainer Container { get; set; }

    public IUserViewModel UserViewModel
    {
        get
        {
            return IoCContainer.Resolve<IUserViewModel>();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

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

<local:ViewModelLocator x:Key="ViewModelLocator"/>
Run Code Online (Sandbox Code Playgroud)

在初始化应用程序时,必须为定位器提供容器的实例:

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

然后在XAML中,您可以干净利用资源:

<UserControl
    DataContext="{Binding Path=UserViewModel, Source={StaticResource ViewModelLocator}}"
    />
    <!-- The other user control properties -->
Run Code Online (Sandbox Code Playgroud)

在设计时,您可以实现MockViewModelLocator:

public class MockViewModelLocator
{

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

}
Run Code Online (Sandbox Code Playgroud)

适当地在XAML中声明它:

<local:MockViewModelLocator x:Key="MockViewModelLocator"/>
Run Code Online (Sandbox Code Playgroud)

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

<UserControl
    d:DataContext="{Binding Path=UserViewModel, Source={StaticResource MockViewModelLocator}}"
    DataContext="{Binding Path=UserViewModel, Source={StaticResource ViewModelLocator}}"
    />
    <!-- The other user control properties -->
Run Code Online (Sandbox Code Playgroud)

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

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

我希望这有帮助.