Dependency Injection for Windows Universal Apps

Dependency Injection fördert gut strukturierten, lesbaren und testbaren Code.

Doch wie kann man das in einer Windows Universal App machen? Für .NET Core gibt es von Microsoft ein eigenes Dependency Injection Framework.

In den folgenden Abschnitten wird gezeigt, wie man das Framework zum Laufen bekommt.

Hinzufügen vom Framework

NuGet Paketverwaltung öffnen und Microsoft.Extensions.DependencyInjection installieren:

Interfaces und Implementierungen erstellen

public interface IPersonProvider
{
    ObservableCollection<Person> AvailablePersons { get; }
    void CreatePerson(string firstName, string lastName);
}
 
public interface ILoggingService
{
    void Log(string message);
}
 
internal class PersonProvider : IPersonProvider
{
    private readonly ILoggingService _loggingService;
 
    public PersonProvider(ILoggingService loggingService)
    {
        if(loggingService==null)
        {
            throw new ArgumentNullException(nameof(loggingService));
        }
        _loggingService = loggingService;
    }
 
    public ObservableCollection<Person> AvailablePersons { get; } = new ObservableCollection<Person>();
 
    public void CreatePerson(string firstName, string lastName)
    {
        _loggingService.Log($"{nameof(CreatePerson)} is called with: {firstName} {lastName}");
        AvailablePersons.Add(new Person { FirstName = firstName, LastName = lastName });
    }
}
internal class LoggingService : ILoggingService
{
    public void Log(string message)
    {
        Debug.WriteLine("Log: " + message);
    }
}

Zugriff ermöglichen

Im Code sollten nur noch die Interfaces benutzt werden und keine Konstruktoren explizit aufgerufen werden.

Mit folgender singleton Klasse können wir Instanzen anfordern:

public class ResolutionRoot
{
    public static ResolutionRoot Instance { get; } = new ResolutionRoot();
    public IServiceProvider Container { get; }
 
    private ResolutionRoot()
    {
        ServiceCollection services = new ServiceCollection();
        RegisterServices(services);
        Container = services.BuildServiceProvider();
    }
 
    private void RegisterServices(ServiceCollection services)
    {
        services.AddTransient<ILoggingService, LoggingService>();
        services.AddTransient<IPersonProvider, PersonProvider>();
    }
}

Um nun einen Person-Provider zu bekommen, reicht folgender Aufruf:

ResolutionRoot.Instance.Container.GetService<IPersonProvider>();

Dabei wird automatisch eine LoggingService-Instanz mit angelegt, da der Konstruktor von PersonProvider diese benötigt.

Wenn in folgender Zeile: services.AddTransient<IPersonProvider, PersonProvider>();

Statt AddTransient die Methode AddSingleton benutzt wird, sorgt das Framework dafür, dass immer die gleiche Instanz genommen wird.

Ein Kommentar

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert