다음을 통해 공유


Ioc(제어 반전)

MVVM 패턴을 사용하여 애플리케이션의 코드베이스에서 모듈성을 높이는 데 사용할 수 있는 일반적인 패턴은 어떤 형태의 제어 반전을 사용하는 것입니다. 특히 가장 일반적인 솔루션 중 하나는 백 엔드 클래스(즉, viewmodel 생성자에 매개 변수로 전달됨)에 삽입되는 여러 서비스를 만드는 데 사용되는 종속성 주입을 사용하는 것입니다. 이렇게 하면 이러한 서비스를 사용하는 코드가 이러한 서비스의 구현 세부 정보에 의존하지 않고 이러한 서비스의 구체적인 구현을 쉽게 교환할 수 있습니다. 또한 이 패턴을 사용하면 필요한 경우 삽입되는 서비스를 통해 추상화하여 백 엔드 코드에 플랫폼별 기능을 쉽게 사용할 수 있습니다.

MVVM 도구 키트는 이 패턴의 사용을 용이하게 하는 기본 제공 API를 제공하지 않습니다. 패키지와 같은 Microsoft.Extensions.DependencyInjection 전용 라이브러리가 이미 있으며, 이는 완전히 기능적이고 강력한 DI API 집합을 제공하고 설정 및 사용하기 IServiceProvider쉬운 역할을 합니다. 다음 가이드에서는 이 라이브러리를 참조하고 MVVM 패턴을 사용하여 애플리케이션에 통합하는 방법에 대한 일련의 예제를 제공합니다.

플랫폼 API: Ioc

서비스 구성 및 해결

첫 번째 단계는 인스턴스를 IServiceProvider 선언하고 일반적으로 시작 시 필요한 모든 서비스를 초기화하는 것입니다. 예를 들어 UWP에서(하지만 다른 프레임워크에서도 유사한 설정을 사용할 수 있음):

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 여기서 속성은 시작 시 초기화되고 모든 애플리케이션 서비스 및 viewmodel이 등록됩니다. 애플리케이션의 다른 보기에서 속성에 쉽게 액세스 Services 하는 데 사용할 수 있는 새 Current 속성도 있습니다. 예를 들면 다음과 같습니다.

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

// Use the files service here...

여기서 중요한 측면은 각 서비스가 플랫폼별 API를 매우 잘 사용할 수 있다는 점이지만, 이러한 API는 모두 코드에서 사용하는 인터페이스를 통해 추상화되므로 인스턴스를 확인하고 이를 사용하여 작업을 수행할 때마다 걱정할 필요가 없습니다.

생성자 주입

사용할 수 있는 강력한 기능 중 하나는 "생성자 주입"입니다. 즉, DI 서비스 공급자는 요청되는 형식의 인스턴스를 만들 때 등록된 서비스 간의 간접 종속성을 자동으로 해결할 수 있습니다. 다음 서비스를 고려합니다.

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

여기서는 인터페이스를 FileLogger 구현하는 IFileLogger 형식과 요구 사항 및 IConsoleService 인스턴스가 IFilesService 있습니다. 생성자 주입은 DI 서비스 공급자가 다음과 같이 필요한 모든 서비스를 자동으로 수집한다는 것을 의미합니다.

/// <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 서비스 공급자는 필요한 모든 서비스가 등록되어 있는지 자동으로 확인한 다음, 해당 서비스를 검색하고 등록된 IFileLogger 구체적인 형식에 대한 생성자를 호출하여 인스턴스를 반환합니다.

viewmodel은 어떻습니까?

서비스 공급자의 이름에는 "서비스"가 있지만 실제로 viewmodel을 비롯한 모든 클래스의 인스턴스를 확인하는 데 사용할 수 있습니다. 위에서 설명한 것과 동일한 개념이 생성자 주입을 포함하여 여전히 적용됩니다. 생성자를 통해 인스턴스 및 인스턴스를 IContactsService 사용하는 형식이 IPhoneService 있다고 ContactsViewModel 상상해 보십시오. 다음과 같은 메서드를 ConfigureServices 사용할 수 있습니다.

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

그런 다음 ContactsView, 다음과 같이 데이터 컨텍스트를 할당합니다.

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

추가 문서

자세한 내용은 Microsoft.Extensions.DependencyInjection여기를 참조 하세요.

예제

  • 샘플 앱(여러 UI 프레임워크의 경우)을 확인하여 작동 중인 MVVM 도구 키트를 확인합니다.
  • 단위 테스트에서 더 많은 예제를 찾을 수도 있습니다.