2016-05-26 24 views
7

Ho un'app basata su Template10 e desidero gestire l'iniezione delle dipendenze utilizzando IoC. Sono propenso ad usare Unity per questo. La mia app è suddivisa in tre gruppi:Come utilizzare un contenitore Unity IoC con Template10?

  1. UI (app universale)
  2. UI Logic (Biblioteca Universale)
  3. Nucleo Logic (Biblioteca Portable).

ho queste domande:

  1. Dovrei usare un unico contenitore per l'intera applicazione o crearne uno per ogni gruppo?
  2. Dove devo creare il contenitore (i) e registrare i miei servizi?
  3. In che modo le diverse classi nei vari assiemi devono accedere ai contenitori? Modello Singleton?

Ho letto molto su DI e IoC ma ho bisogno di sapere come applicare tutta la teoria in pratica, in particolare in Template10.

Il codice di registrare:

// where should I put this code? 
var container = new UnityContainer(); 
container.RegisterType<ISettingsService, RoamingSettingsService); 

E poi il codice per recuperare le istanze:

var container = ??? 
var settings = container.Resolve<ISettingsService>(); 
+0

Possibile duplicato [IOC/DI - Perché devo fare riferimento a tutti i livelli/assemblee in entrata applicazione?] (http://stackoverflow.com/questions/9501604/ioc-di-why-do-i-have-to-reference-all-layers-assemblies-in-entry-application) – NightOwl888

risposta

3

non familiarità con Unity Container.

Il mio esempio utilizza LightInject, è possibile applicare un concetto simile utilizzando Unity. Per abilitare DI su ViewModel è necessario eseguire l'override di ResolveForPage su App.xaml.cs sul progetto.

public class MainPageViewModel : ViewModelBase 
{ 
    ISettingsService _setting; 
    public MainPageViewModel(ISettingsService setting) 
    { 
     _setting = setting; 
    } 
} 


[Bindable] 
sealed partial class App : Template10.Common.BootStrapper 
{ 
    internal static ServiceContainer Container; 

    public App() 
    { 
     InitializeComponent(); 
    } 

    public override async Task OnInitializeAsync(IActivatedEventArgs args) 
    { 
     if(Container == null) 
      Container = new ServiceContainer(); 

     Container.Register<INavigable, MainPageViewModel>(typeof(MainPage).FullName); 
     Container.Register<ISettingsService, RoamingSettingsService>(); 

     // other initialization code here 

     await Task.CompletedTask; 
    } 

    public override INavigable ResolveForPage(Page page, NavigationService navigationService) 
    { 
     return Container.GetInstance<INavigable>(page.GetType().FullName); 
    } 
} 

Template10 sarà automaticamente impostato DataContext-MainPageViewModel, se si desidera utilizzare il {x:bind}MainPage.xaml.cs:

public class MainPage : Page 
{ 
    MainPageViewModel _viewModel; 

    public MainPageViewModel ViewModel 
    { 
     get { return _viewModel??(_viewModel = (MainPageViewModel)this.DataContext); } 
    } 
} 
+0

Grazie per la risposta! Questo ha funzionato bene per me! C'è un modo per iniettare VM nella vista Shell? –

+0

@NickGoloborodko Non ho capito bene la tua domanda, forse dovresti creare una nuova domanda SO su questo? –

0

ecco un piccolo esempio di come io uso l'Unità e Template 10.

1 Crea un ViewModel

I creato anche una classe DataService per creare un elenco di persone. Dai un'occhiata all'annotazione [Dipendenza].

public class UnityViewModel : ViewModelBase 
{ 
    public string HelloMessage { get; } 

    [Dependency] 
    public IDataService DataService { get; set; } 

    private IEnumerable<Person> people; 
    public IEnumerable<Person> People 
    { 
     get { return people; } 
     set { this.Set(ref people, value); } 
    } 

    public UnityViewModel() 
    { 
     HelloMessage = "Hello !"; 
    } 

    public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, 
     IDictionary<string, object> suspensionState) 
    { 
     await Task.CompletedTask; 
     People = DataService.GetPeople(); 
    } 
} 

2. Creare una classe per creare e riempire il vostro UnityContainer

Aggiungere l'UnityViewModel e la DataService al unityContainer. Creare una proprietà per risolvere UnityViewModel.

public class UnitiyLocator 
{ 
    private static readonly UnityContainer unityContainer; 

    static UnitiyLocator() 
    { 
     unityContainer = new UnityContainer(); 
     unityContainer.RegisterType<UnityViewModel>(); 
     unityContainer.RegisterType<IDataService, RuntimeDataService>(); 
    } 

    public UnityViewModel UnityViewModel => unityContainer.Resolve<UnityViewModel>(); 
} 

3. Aggiungere l'UnityLocator per la vostra applicazione.XAML

<common:BootStrapper x:Class="Template10UWP.App" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:common="using:Template10.Common" 
       xmlns:mvvmLightIoc="using:Template10UWP.Examples.MvvmLightIoc" 
       xmlns:unity="using:Template10UWP.Examples.Unity"> 


<Application.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="Styles\Custom.xaml" /> 
      <ResourceDictionary> 
       <unity:UnitiyLocator x:Key="UnityLocator" /> 
      </ResourceDictionary> 
     </ResourceDictionary.MergedDictionaries> 

     <!-- custom resources go here --> 

    </ResourceDictionary> 
</Application.Resources> 

4. Creare la pagina

Utilizzare l'UnityLocator per impostare l'UnityViewModel come DataContext e si legano le proprietà ai controlli

<Page 
x:Class="Template10UWP.Examples.Unity.UnityMainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:Template10UWP.Examples.Unity" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
DataContext="{Binding Source={StaticResource UnityLocator}, Path=UnityViewModel}" 
mc:Ignorable="d"> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <TextBlock Text="{Binding HelloMessage}" HorizontalAlignment="Center" 
       VerticalAlignment="Center" /> 

    <ListBox Grid.Row="1" ItemsSource="{Binding People}" DisplayMemberPath="FullName"> 

    </ListBox> 
</Grid> 

Il DataService verrà iniettato automaticamente quando la pagina risolve UnityViewModel.

Ora alle tue domande

  1. Questo dipende da come i progetti dipendono l'uno dall'altro. Non sono sicuro quale sia la soluzione migliore, ma penso che proverei a usare UnityContainer e metterlo nella libreria principale.

  2. spero risposto a questa domanda i miei esempi

  3. Spero risposto a questa domanda i miei esempi