Ioc (Denetimin ters çevrilmesi)

MVVM deseni kullanılarak bir uygulamanın kod tabanında modülerliği artırmak için kullanılabilecek yaygın bir desen, denetimin bir tür tersini kullanmaktır. Özellikle en yaygın çözümlerden biri, arka uç sınıflarına eklenen bir dizi hizmet oluşturmak (yani görünüm modeli oluşturucularına parametre olarak geçirilen) bağımlılık ekleme özelliğini kullanmaktır. Bu, bu hizmetleri kullanan kodun bu hizmetlerin uygulama ayrıntılarına güvenmemesini sağlar ve ayrıca bu hizmetlerin somut uygulamalarının değişimini kolaylaştırır. Bu desen, platforma özgü özelliklerin, bir servis aracılığıyla soyutlanıp ardından gereken yerlere enjekte edilerek arka uç kodunda kullanılabilir hale getirilmesini de kolaylaştırır.

MVVM Toolkit, bu modelin kullanımını kolaylaştırmak için yerleşik API'ler sağlamaz; çünkü bunun için özel olarak tasarlanmış, Microsoft.Extensions.DependencyInjection paketi gibi adanmış kitaplıklar zaten mevcuttur. Bu paket, tam özellikli ve güçlü bir DI API kümesi sağlar ve kurulumu ve kullanımı kolay bir IServiceProvider görevi görür. Aşağıdaki kılavuz, bu kitaplığı ele alacak ve MVVM desenini kullanarak uygulamalara nasıl entegre edileceğini gösteren bir dizi örnek sunacaktır.

Platform API'leri:Ioc

Hizmetleri yapılandırma ve çözme

İlk adım bir IServiceProvider örneği bildirmek ve genellikle başlangıçta gerekli tüm hizmetleri başlatmaktır. Örneğin, UWP'de (ancak benzer bir kurulum diğer çerçevelerde de kullanılabilir):

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();
    }
}

Services Burada özellik başlangıçta başlatılır ve tüm uygulama hizmetleri ve görünüm modelleri kaydedilir. Ayrıca, uygulamadaki diğer görünümlerden Services özelliğine kolayca erişmek için kullanılabilecek yeni bir Current özelliği de vardır. Örneğin:

IFilesService filesService = App.Current.Services.GetService<IFilesService>();

// Use the files service here...

Buradaki önemli nokta, her hizmetin platforma özgü API'leri çok iyi kullanabilecek olmasıdır, ancak bunların hepsi kodumuzun kullandığı arabirim aracılığıyla soyutlandığından, yalnızca bir örneği çözümleyip işlemleri gerçekleştirmek için kullandığımızda bunlar hakkında endişelenmemiz gerekmez.

Kurucu enjeksiyonu

Kullanılabilir güçlü bir özellik olan "oluşturucu ekleme"dir. Bu, DI hizmet sağlayıcısının istenen türün örneklerini oluştururken kayıtlı hizmetler arasındaki dolaylı bağımlılıkları otomatik olarak çözümleyebileceği anlamına gelir. Aşağıdaki hizmeti göz önünde bulundurun:

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

Burada, IFileLogger arabirimini uygulayan ve IFilesService ile IConsoleService örneklerini gerektiren bir FileLogger türümüz var. Oluşturucu ekleme, DI hizmet sağlayıcısının aşağıdaki gibi tüm gerekli hizmetleri otomatik olarak topladığı anlamına gelir:

/// <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>();

DI hizmet sağlayıcısı gerekli tüm hizmetlerin kaydedilip kaydedilmediğini otomatik olarak denetler, ardından bunları alır ve örneğin döndürülmesi için kayıtlı IFileLogger somut türün oluşturucusunu çağırır.

Peki ya ViewModel’ler?

Hizmet sağlayıcısının adında "hizmet" vardır, ancak görünüm modelleri de dahil olmak üzere herhangi bir sınıfın örneklerini çözümlemek için kullanılabilir! Oluşturucu ekleme de dahil olmak üzere yukarıda açıklanan kavramlar hala geçerlidir. Oluşturucusu aracılığıyla bir IContactsService ve bir IPhoneService örneği kullanan bir ContactsViewModel türüne sahip olduğumuzu düşünün. Bunun gibi bir ConfigureServices yöntemimiz olabilir:

/// <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();
}

Ardından, ContactsView içinde veri bağlamını şu şekilde atarız:

public ContactsView()
{
    this.InitializeComponent();
    this.DataContext = App.Current.Services.GetService<ContactsViewModel>();
}

Diğer belgeler

hakkında Microsoft.Extensions.DependencyInjectiondaha fazla bilgi için buraya bakın.

Örnekler