2016-05-31 9 views
0

Ich bin sehr überrascht, dass diese Frage nicht in jedem IoC/MVVM-Tutorial behandelt wird, so dass ich hoffentlich etwas offensichtlich fehlen.Autofac: Relate LifetimeScope auf die Lebensdauer von ViewModel in MVVM

Kurz gesagt, meine Frage ist: Wie kann ich ein Autofac LifeTimeScope auf die Lebensdauer eines ViewModel beziehen.

Betrachten Sie die einfache Anwendung unten.

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

Diese Anwendung von fünf Ansichten bestehen:

  • Mainview
  • Listview
  • ADetailView
  • BDetailView
  • CDetailView

sowie fünf Viewmodels

  • MainViewModel
  • ListViewModel
  • ADetalViewModel
  • BDetalViewModel
  • CDetalViewModel

Die Hauptansicht wäre in etwa so strukturiert werden.

<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> 

So ist es eine Benutzeroberfläche Template-Laufwerk, in dem die Vorlage Typ eine Änderung der korrekten Sicht auslösen. Um dies zu tun, müssen wir ein ViewModel des korrekten Typs instanziieren und es CurrentDetailViewModel in MainViewModel zuweisen.

Jetzt komme ich zu der Frage. Ich würde sehr gerne die Erstellung dieses Detail-Viewmodel auch die Erstellung eines LifetimeScope auslösen. Dann werden alle seine Abhängigkeiten innerhalb dieses Bereichs liegen und können leicht entsorgt werden, wenn zu einem anderen Ansichts-/Ansichtsmodell gewechselt wird.

Das muss ein sehr, sehr, sehr häufiger Anwendungsfall für Autofac sein und ich bin sehr neugierig, wie andere Leute es angehen.

+0

Ich bin nicht mit Autofac bekannt, leider aber ich denke, ich in der Regel zu verstehen, was Sie reden. Ich lege immer die Lebensdauer der Abhängigkeiten im Bootstrapper fest. Warum möchten Sie eine Aktion zum Festlegen der Lebensdauer von Abhängigkeiten in der Laufzeit auslösen? – EngineerSpock

+0

Ich spreche nicht über lebenslange Spezifikation, sondern Schaffung eines temporären Lebensdauer-Scope, die nur existieren, während die Detailansicht sichtbar ist. Unity hat die Lifetime Manager, aber ich bin mir nicht sicher, ob es genau das gleiche wie Lifetimecope ist. Stellen Sie sich einen Webserver vor, er erstellt für jede Anfrage ein Lebensdauerszenario, und wenn Sie Instanzen auflösen, ist das normale Verhalten, dass diese Instanzen in diesem Lebensdau- er erstellt und folglich damit verworfen werden. – sunefred

+0

Wenn ich Sie richtig verstehe, haben Sie Implementierer mit nicht verwalteten Ressourcen? (In anderen Fällen verstehe ich nicht den Grund, warum Sie diese Funktion möchten, da verwaltete Implementierer nach Abschluss von ViewModel nicht mehr erreichbar sind). Ich muss verstehen, warum, vorzugsweise an einem praktischen Beispiel, dass Sie diese Funktion haben, kann mir helfen, ich hoffe) – EngineerSpock

Antwort

0

Ich werde meinen aktuellen Ansatz der Antwortliste hinzufügen und hoffentlich wird jemand hinzufügen oder eine bessere Antwort geben.

Ich habe von Owned Gebrauch gemacht. Wenn der Container etwas gefunden hat, das als Owned<> deklariert ist, wird die Instanz in ihrem eigenen neuen Lebensdau- er erstellt. Alle Abhängigkeiten enden dann (standardmäßig) auch in diesem Lebenszeitbereich. Das Life-Time-Scope muss jedoch manuell durch Aufruf von Dispose() zerstört werden. Im folgenden Beispiel kombiniere ich Owned mit Func, um eine Factory zum Erstellen einer beliebigen Anzahl von im Besitz befindlichen Instanzen zu erhalten.

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; 
        } 
       } 
      } 
     )); 
    } 
} 
Verwandte Themen