Внедрение конструктора Silverlight в модель View + Design

Im пытается справиться с написанием проверяемых ViewModels в Silverlight 4. В настоящее время я использую свет MVVM.

Im использует AutoFac, и IoCContainer отлично справляется со своей работой. Однако для ввода в конструктор 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 для разрешения viewmodels для просмотров, как это было указано выше в подходе к методу XAML, и пойти по этому маршруту?

Спасибо.

Ответ 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, и во время выполнения вы будете использовать свой реальный сервис.

Таким образом, вы не теряете данные о времени разработки, и вам не нужно жертвовать чистотой методологии внедрения зависимостей в ваших моделях просмотра.

Надеюсь, это поможет.