2016-05-31 5 views
0

Я очень удивлен, что этот вопрос не рассматривается в каждом учебном пособии по IoC/MVVM, поэтому, надеюсь, я не вижу чего-то очевидного.Autofac: связать LifeTimeScope со временем жизни ViewModel в MVVM

Короче говоря, мой вопрос: как я могу связать Autofac LifeTimeScope со временем жизни ViewModel.

Рассмотрите простое приложение ниже.

------------------------------------------------- 
|           _ o x | 
------------------------------------------------- 
|   |          | 
| Item A |          | 
| Item B |  DetailView for Item A   | 
| Item C |          | 
|   |          | 
|------------------------------------------------ 

Это приложение состоит из пяти видов:

  • MainView
  • ListView
  • ADetailView
  • BDetailView
  • CDetailView

, а также пять ViewModels

  • MainViewModel
  • ListViewModel
  • ADetalViewModel
  • BDetalViewModel
  • CDetalViewModel

Основной вид будет структурирована что-то вроде этого.

<Grid Margin="5"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="1*"></ColumnDefinition> 
     <ColumnDefinition Width="5"></ColumnDefinition> 
     <ColumnDefinition Width="2*"></ColumnDefinition> 
    </Grid.ColumnDefinitions> 

    <ListView Grid.Column="0"> 
    </ListView> 

    <GridSplitter Grid.Column="1"/> 

    <Border Grid.Column="2"> 
     <Border.Resources> 
      <DataTemplate DataType="{x:Type vm:ADetailViewModel}"> 
       <vw:ADetailView></vw:ADetailView> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type vm:BDetailViewModel}"> 
       <vw:BDetailView></vw:BDetailView> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type vm:CDetailViewModel}"> 
       <vw:CDetailView></vw:CDetailView> 
      </DataTemplate> 
     </Border.Resources> 
     <ContentPresenter Content="{Binding CurrentDetailViewModel}"></ContentPresenter> 
    </Border> 

</Grid> 

Таким образом, это пользовательский интерфейс для диска шаблона, где тип шаблона вызовет изменение правильного вида. Для этого мы должны создать экземпляр ViewModel правильного типа и назначить его CurrentDetailViewModel в MainViewModel.

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

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

+0

Я не знаком с Autofac, к сожалению, но я думаю, что я вообще понимаю, что вы говорите. Я всегда устанавливал время жизни зависимостей в загрузчике. Почему вы хотите инициировать некоторые действия по определению времени жизни зависимостей во время выполнения? – EngineerSpock

+0

Я не говорю о спецификации на всю жизнь, а скорее создаю временный lifetimecope, который существует только в то время, когда отображается подробный вид. У Unity есть менеджеры по жизни, но я не уверен, что это точно так же, как lifetimecope. Представьте себе веб-сервер, он создает lifetimecope для каждого запроса, и если вы разрешаете экземпляры, нормальное поведение для этих экземпляров должно быть создано в этом lifetimecope и, следовательно, расположено с ним. – sunefred

+0

Если я правильно вас понимаю, у вас есть разработчики, у которых есть неуправляемые ресурсы? (в другом случае я не понимаю причину, по которой вам нужна эта функция, поскольку управляемые исполнители будут собирать мусор после того, как ViewModel станет недоступным). Мне нужно понять, ПОЧЕМУ, желательно на практическом примере, вы хотите эту функцию, это может помочь мне, чтобы помочь вам, я надеюсь) – EngineerSpock

ответ

0

Я добавлю свой текущий подход к списку ответов и, надеюсь, кто-то добавит или даст лучший ответ.

Я использовал Owned. Когда контейнер найдет что-то объявленное как Owned<>, он создаст экземпляр в своем собственном новом lifetimecope. Любые зависимости затем (по умолчанию) также оказываются в этом lifetimescope. Манипулятор жизни должен быть уничтожен вручную, но позвонив по номеру Dispose(). В приведенном ниже примере я объединяю Owned with Func, чтобы получить фабрику для создания любого количества принадлежащих экземпляров.

Constructor:

private readonly Func<Owned<ADetailViewModel> _aFactory; 
private readonly Func<Owned<BDetailViewModel> _bFactory; 
private readonly Func<Owned<CDetailViewModel> _cFactory; 

private IDisposable _currentOwned; 

public MainViewModel(Func<int, Owned<ADetailViewModel>> aFactory, 
        Func<int, Owned<BDetailViewModel>> bFactory, 
        Func<int, Owned<CDetailViewModel>> cFactory) 
{ 
    _aFactory= aFactory; 
    _bFactory= bFactory; 
    _cFactory= cFactory; 
} 

SwitchDetailViewCommand:

private RelayCommand<IListItemViewModel> _switchDetailViewCommand ; 
public RelayCommand<IListItemViewModel> SwitchDetailViewCommand 
{ 
    get 
    { 
     return _switchDetailViewCommand ?? (_switchDetailViewCommand = new RelayCommand<IListItemViewModel>(
      (listitem) => 
      { 
       if (_currentOwned != null) 
       { 
        _currentOwned.Dispose(); 
       } 
       switch (listitem.Type) 
       { 
        case "A": 
        { 
         var aOwned = _aFactory(); 
         _currentOwned = aOwned; 
         CurrentDetailViewModel = _aOwned.Value; 
         break; 
        } 
        case "B": 
        { 
         var bOwned = _bFactory(); 
         _currentOwned = bOwned; 
         CurrentDetailViewModel = _bOwned.Value; 
         break; 
        } 
        case "C": 
        { 
         var cOwned = _cFactory(); 
         _currentOwned = cOwned; 
         CurrentDetailViewModel = _cOwned.Value; 
         break; 
        } 
        default: 
        { 
         break; 
        } 
       } 
      } 
     )); 
    } 
}