Un modello comune che può essere usato per aumentare la modularità nella codebase di un'applicazione usando il modello MVVM consiste nell'usare una forma di inversione del controllo. Una delle soluzioni più comuni in particolare consiste nell'usare l'inserimento delle dipendenze, che consiste nella creazione di un certo numero di servizi inseriti in classi back-end (ad esempio, passate come parametri ai costruttori del modello di visualizzazione), che consente al codice di usare questi servizi di non basarsi sui dettagli di implementazione di questi servizi e semplifica anche lo scambio delle implementazioni concrete di questi servizi. Questo modello semplifica anche la disponibilità di funzionalità specifiche della piattaforma per il codice back-end, astraendole tramite un servizio che viene quindi inserito dove necessario.
MVVM Toolkit non fornisce API predefinite per facilitare l'uso di questo modello, perché esistono già librerie dedicate specifiche per questo, ad esempio il Microsoft.Extensions.DependencyInjection pacchetto, che fornisce un set completo e potente di API di inserimento e funge da semplice da configurare e usare IServiceProvider. La guida seguente farà riferimento a questa libreria e fornirà una serie di esempi di come integrarlo nelle applicazioni usando il modello MVVM.
Il primo passaggio consiste nel dichiarare un'istanza IServiceProvider e inizializzare tutti i servizi necessari, in genere all'avvio. Ad esempio, in UWP (ma una configurazione simile può essere usata anche in altri framework):
public sealed partial class App : Application
{
public App()
{
Services = ConfigureServices();
this.InitializeComponent();
}
/// <summary>
/// Gets the current <see cref="App"/> instance in use
/// </summary>
public new static App Current => (App)Application.Current;
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
/// <summary>
/// Configures the services for the application.
/// </summary>
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.AddSingleton<IFilesService, FilesService>();
services.AddSingleton<ISettingsService, SettingsService>();
services.AddSingleton<IClipboardService, ClipboardService>();
services.AddSingleton<IShareService, ShareService>();
services.AddSingleton<IEmailService, EmailService>();
return services.BuildServiceProvider();
}
}
In questo caso la Services proprietà viene inizializzata all'avvio e vengono registrati tutti i servizi dell'applicazione e i modelli di visualizzazione. È anche disponibile una nuova Current proprietà che può essere usata per accedere facilmente alla Services proprietà da altre visualizzazioni nell'applicazione. Ad esempio:
IFilesService filesService = App.Current.Services.GetService<IFilesService>();
// Use the files service here...
L'aspetto chiave è che ogni servizio può essere molto utile usare API specifiche della piattaforma, ma poiché queste sono tutte astratte tramite l'interfaccia usata dal codice, non è necessario preoccuparsi di esse ogni volta che si sta risolvendo un'istanza e usandola per eseguire operazioni.
Inserimento del costruttore
Una funzionalità potente disponibile è l'inserimento del costruttore, il che significa che il provider di servizi di inserimento delle dipendenze è in grado di risolvere automaticamente le dipendenze indirette tra i servizi registrati durante la creazione di istanze del tipo richiesto. Si consideri il servizio seguente:
public class FileLogger : IFileLogger
{
private readonly IFilesService FileService;
private readonly IConsoleService ConsoleService;
public FileLogger(
IFilesService fileService,
IConsoleService consoleService)
{
FileService = fileService;
ConsoleService = consoleService;
}
// Methods for the IFileLogger interface here...
}
Qui è disponibile un FileLogger tipo che implementa l'interfaccia IFileLogger e richiede IFilesService le istanze e IConsoleService . L'inserimento del costruttore indica che il provider di servizi di inserimento delle dipendenze raccoglie automaticamente tutti i servizi necessari, come indicato di seguito:
/// <summary>
/// Configures the services for the application.
/// </summary>
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.AddSingleton<IFilesService, FilesService>();
services.AddSingleton<IConsoleService, ConsoleService>();
services.AddSingleton<IFileLogger, FileLogger>();
return services.BuildServiceProvider();
}
// Retrieve a logger service with constructor injection
IFileLogger fileLogger = App.Current.Services.GetService<IFileLogger>();
Il provider di servizi di inserimento delle dipendenze verificherà automaticamente se tutti i servizi necessari sono registrati, quindi li recupererà e richiamerà il costruttore per il tipo concreto registrato IFileLogger , per ottenere la restituzione dell'istanza.
Che ne dici dei modelli di visualizzazione?
Un provider di servizi ha "servizio" nel nome, ma può effettivamente essere usato per risolvere le istanze di qualsiasi classe, inclusi i modelli di visualizzazione. Gli stessi concetti illustrati in precedenza si applicano ancora, incluso l'inserimento del costruttore. Si supponga di avere un ContactsViewModel tipo, usando un oggetto IContactsService e un'istanza IPhoneService tramite il relativo costruttore. È possibile avere un ConfigureServices metodo simile al seguente:
/// <summary>
/// Configures the services for the application.
/// </summary>
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
// Services
services.AddSingleton<IContactsService, ContactsService>();
services.AddSingleton<IPhoneService, PhoneService>();
// Viewmodels
services.AddTransient<ContactsViewModel>();
return services.BuildServiceProvider();
}
In , quindi ContactsView, si assegnerebbe il contesto dati come segue:
public ContactsView()
{
this.InitializeComponent();
this.DataContext = App.Current.Services.GetService<ContactsViewModel>();
}
Altri documenti
Per altre info su Microsoft.Extensions.DependencyInjection, vedere qui.
È anche possibile trovare altri esempi negli unit test.
Collabora con noi su GitHub
L'origine di questo contenuto è disponibile in GitHub, in cui è anche possibile creare ed esaminare i problemi e le richieste pull. Per ulteriori informazioni, vedere la guida per i collaboratori.
Feedback su MVVM Toolkit
MVVM Toolkit è un progetto di open source. Selezionare un collegamento per fornire feedback:
Comprendere e implementare l'inserimento delle dipendenze in un'app ASP.NET Core. Usare il contenitore di servizi predefinito ASP.NET Core per gestire le dipendenze. Registrare i servizi con il contenitore del servizio.