의 종속성 확인 Xamarin.Forms

Download Sample 샘플 다운로드

이 문서에서는 애플리케이션의 종속성 주입 컨테이너가 Xamarin.Forms 사용자 지정 렌더러, 효과 및 DependencyService 구현의 생성 및 수명을 제어할 수 있도록 종속성 확인 방법을 삽입하는 방법을 설명합니다. 이 문서의 코드 예제는 컨테이너 샘플을 사용하여 종속성 확인에서 가져옵니다.

MVVM(Model-View-ViewModel) 패턴을 사용하는 애플리케이션의 Xamarin.Forms 컨텍스트에서 종속성 주입 컨테이너를 사용하여 뷰 모델을 등록 및 확인하고 서비스를 등록하고 보기 모델에 삽입할 수 있습니다. 뷰 모델을 만드는 동안 컨테이너는 필요한 모든 종속성을 삽입합니다. 이러한 종속성을 만들지 않은 경우 컨테이너는 먼저 종속성을 만들고 확인합니다. 종속성 주입에 대한 자세한 내용은 종속성을 보기 모델에 삽입하는 예제를 포함하여 종속성 주입을 참조하세요.

플랫폼 프로젝트에서 형식의 생성 및 수명에 대한 제어는 일반적으로 Xamarin.Forms메서드를 사용하여 사용자 지정 렌더러, 효과 및 DependencyService 구현의 인스턴스를 만드는 데 사용됩니다Activator.CreateInstance. 아쉽게도 이러한 형식의 생성 및 수명 및 종속성을 삽입하는 기능에 대한 개발자 제어가 제한됩니다. 이 동작은 애플리케이션의 종속성 주입 컨테이너 또는 Xamarin.Forms형식을 만드는 방법을 제어하는 종속성 확인 메서드 Xamarin.Forms 를 삽입하여 변경할 수 있습니다. 그러나 종속성 확인 메서드 Xamarin.Forms를 삽입할 필요는 없습니다. Xamarin.Forms 종속성 확인 메서드가 삽입되지 않은 경우 플랫폼 프로젝트에서 형식의 수명을 계속 만들고 관리합니다.

참고 항목

이 문서에서는 종속성 주입 컨테이너를 사용하여 등록된 형식을 확인하는 종속성 확인 메서드 Xamarin.Forms 를 삽입하는 데 중점을 두고 있지만, 팩터리 메서드를 사용하여 등록된 형식을 확인하는 종속성 확인 방법을 삽입할 수도 있습니다. 자세한 내용은 팩터리 메서드 샘플을 사용하여 종속성 확인을 참조하세요.

종속성 확인 메서드 삽입

클래스는 DependencyResolver 메서드를 사용하여 ResolveUsing 종속성 확인 메서드를 삽입하는 Xamarin.Forms기능을 제공합니다. 그런 다음 특정 형식의 인스턴스가 필요한 경우 Xamarin.Forms 종속성 확인 메서드에 인스턴스를 제공할 수 있는 기회가 제공됩니다. 종속성 확인 메서드가 요청된 형식 Xamarin.Forms 에 대해 반환 null 되는 경우 메서드를 사용하여 Activator.CreateInstance 형식 인스턴스 자체를 만들려고 다시 시도합니다.

다음 예제에서는 메서드를 사용하여 종속성 확인 메서드를 ResolveUsing 설정하는 방법을 보여줍니다.

using Autofac;
using Xamarin.Forms.Internals;
...

public partial class App : Application
{
    // IContainer and ContainerBuilder are provided by Autofac
    static IContainer container;
    static readonly ContainerBuilder builder = new ContainerBuilder();

    public App()
    {
        ...
        DependencyResolver.ResolveUsing(type => container.IsRegistered(type) ? container.Resolve(type) : null);
        ...
    }
    ...
}

이 예제에서 종속성 확인 메서드는 Autofac 종속성 주입 컨테이너를 사용하여 컨테이너에 등록된 모든 형식을 확인하는 람다 식으로 설정됩니다. 그렇지 않으면 null 형식을 확인하려고 하면 반환됩니다 Xamarin.Forms .

참고 항목

종속성 주입 컨테이너에서 사용하는 API는 컨테이너와 관련이 있습니다. 이 문서의 코드 예제에서는 Autofac을 종속성 주입 컨테이너로 사용하여 해당 컨테이너와 ContainerBuilder 형식을 IContainer 제공합니다. 대체 종속성 주입 컨테이너를 동일하게 사용할 수 있지만 여기에 나와 있는 것과 다른 API를 사용합니다.

애플리케이션을 시작하는 동안 종속성 확인 방법을 설정할 필요가 없습니다. 언제든지 설정할 수 있습니다. 유일한 제약 조건은 애플리케이션이 Xamarin.Forms 종속성 주입 컨테이너에 저장된 형식을 사용하려고 할 때까지 종속성 확인 방법을 알아야 한다는 것입니다. 따라서 시작 중에 애플리케이션에 필요한 종속성 주입 컨테이너에 서비스가 있는 경우 애플리케이션의 수명 주기 초기에 종속성 확인 방법을 설정해야 합니다. 마찬가지로 종속성 주입 컨테이너가 특정 EffectXamarin.Forms 항목의 생성 및 수명을 관리하는 경우 종속성 확인 방법을 사용하는 Effect뷰를 만들기 전에 알아야 합니다.

Warning

종속성 주입 컨테이너를 사용하여 형식을 등록하고 확인하는 경우, 특히 애플리케이션의 각 페이지 탐색에 대해 종속성이 재구성되는 경우 컨테이너가 각 형식을 만드는 데 리플렉션을 사용하기 때문에 성능 비용이 듭니다. 종속성이 많거나 깊은 경우에는 생성 비용이 많이 증가할 수 있습니다.

형식 등록

종속성 확인 방법을 통해 종속성 주입 컨테이너를 확인하려면 먼저 종속성 주입 컨테이너에 형식을 등록해야 합니다. 다음 코드 예제에서는 샘플 애플리케이션이 Autofac 컨테이너에 대해 클래스에 App 노출하는 등록 방법을 보여 줍니다.

using Autofac;
using Autofac.Core;
...

public partial class App : Application
{
    static IContainer container;
    static readonly ContainerBuilder builder = new ContainerBuilder();
    ...

    public static void RegisterType<T>() where T : class
    {
        builder.RegisterType<T>();
    }

    public static void RegisterType<TInterface, T>() where TInterface : class where T : class, TInterface
    {
        builder.RegisterType<T>().As<TInterface>();
    }

    public static void RegisterTypeWithParameters<T>(Type param1Type, object param1Value, Type param2Type, string param2Name) where T : class
    {
        builder.RegisterType<T>()
               .WithParameters(new List<Parameter>()
        {
            new TypedParameter(param1Type, param1Value),
            new ResolvedParameter(
                (pi, ctx) => pi.ParameterType == param2Type && pi.Name == param2Name,
                (pi, ctx) => ctx.Resolve(param2Type))
        });
    }

    public static void RegisterTypeWithParameters<TInterface, T>(Type param1Type, object param1Value, Type param2Type, string param2Name) where TInterface : class where T : class, TInterface
    {
        builder.RegisterType<T>()
               .WithParameters(new List<Parameter>()
        {
            new TypedParameter(param1Type, param1Value),
            new ResolvedParameter(
                (pi, ctx) => pi.ParameterType == param2Type && pi.Name == param2Name,
                (pi, ctx) => ctx.Resolve(param2Type))
        }).As<TInterface>();
    }

    public static void BuildContainer()
    {
        container = builder.Build();
    }
    ...
}

애플리케이션이 종속성 확인 방법을 사용하여 컨테이너의 형식을 확인하는 경우 일반적으로 플랫폼 프로젝트에서 형식 등록이 수행됩니다. 이를 통해 플랫폼 프로젝트는 사용자 지정 렌더러, 효과 및 DependencyService 구현에 대한 형식을 등록할 수 있습니다.

플랫폼 프로젝트에서 형식 등록 후 메서드를 IContainer 호출 BuildContainer 하여 수행되는 개체를 빌드해야 합니다. 이 메서드는 인스턴스에서 ContainerBuilder Autofac의 Build 메서드를 호출합니다. 이 메서드는 만들어진 등록을 포함하는 새 종속성 주입 컨테이너를 빌드합니다.

다음 섹션에서는 인터페이스를 Logger 구현하는 클래스가 ILogger 클래스 생성자에 삽입됩니다. 클래스는 Logger 메서드를 사용하여 Debug.WriteLine 간단한 로깅 기능을 구현하고 서비스를 사용자 지정 렌더러, 효과 및 DependencyService 구현에 삽입하는 방법을 보여 주는 데 사용됩니다.

사용자 지정 렌더러 등록

샘플 애플리케이션에는 다음 예제에 XAML 원본이 표시된 웹 비디오를 재생하는 페이지가 포함되어 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:video="clr-namespace:FormsVideoLibrary"
             ...>
    <video:VideoPlayer Source="https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4" />
</ContentPage>

보기는 VideoPlayer 비디오 재생 기능을 제공하는 클래스에 의해 VideoPlayerRenderer 각 플랫폼에서 구현됩니다. 이러한 사용자 지정 렌더러 클래스에 대한 자세한 내용은 비디오 플레이어 구현을 참조 하세요.

iOS 및 UWP(유니버설 Windows 플랫폼)VideoPlayerRenderer에서 클래스에는 인수가 필요한 다음 생성자가 있습니다ILogger.

public VideoPlayerRenderer(ILogger logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

모든 플랫폼에서 종속성 주입 컨테이너에 대한 형식 등록은 메서드에 의해 RegisterTypes 수행되며, 이 메서드는 플랫폼이 메서드를 사용하여 LoadApplication(new App()) 애플리케이션을 로드하기 전에 호출됩니다. 다음 예제에서는 iOS 플랫폼의 RegisterTypes 메서드를 보여줍니다.

void RegisterTypes()
{
    App.RegisterType<ILogger, Logger>();
    App.RegisterType<FormsVideoLibrary.iOS.VideoPlayerRenderer>();
    App.BuildContainer();
}

이 예제 Logger 에서 구체적인 형식은 인터페이스 형식에 대한 매핑을 통해 등록되고 VideoPlayerRenderer 형식은 인터페이스 매핑 없이 직접 등록됩니다. 사용자가 뷰가 포함된 VideoPlayer 페이지로 이동하면 종속성 주입 컨테이너에서 형식을 확인하기 VideoPlayerRenderer 위해 종속성 확인 메서드가 호출되며, 이 메서드는 형식을 확인하고 생성자에 삽입 LoggerVideoPlayerRenderer 합니다.

VideoPlayerRenderer Android 플랫폼의 생성자는 인수 외 ILogger 에 인수가 Context 필요하므로 약간 더 복잡합니다.

public VideoPlayerRenderer(Context context, ILogger logger) : base(context)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

다음 예제에서는 Android 플랫폼의 RegisterTypes 메서드를 보여줍니다.

void RegisterTypes()
{
    App.RegisterType<ILogger, Logger>();
    App.RegisterTypeWithParameters<FormsVideoLibrary.Droid.VideoPlayerRenderer>(typeof(Android.Content.Context), this, typeof(ILogger), "logger");
    App.BuildContainer();
}

이 예제에서 메서드는 App.RegisterTypeWithParameters 종속성 주입 컨테이너에 등록합니다 VideoPlayerRenderer . 등록 방법을 사용하면 인스턴스가 MainActivity 인수로 Context 삽입되고 형식이 Logger 인수로 ILogger 삽입됩니다.

효과 등록

샘플 애플리케이션에는 터치 추적 효과를 사용하여 페이지 주위에 인스턴스를 끌어다 주는 BoxView 페이지가 포함되어 있습니다. 다음 Effect 코드를 사용하여 추가 BoxView 됩니다.

var boxView = new BoxView { ... };
var touchEffect = new TouchEffect();
boxView.Effects.Add(touchEffect);

클래스는 TouchEffectRoutingEffect 각 플랫폼에서 클래스에 의해 TouchEffect 구현되는 클래스입니다 PlatformEffect. 플랫폼 TouchEffect 클래스는 페이지 주변을 BoxView 끌기 위한 기능을 제공합니다. 이러한 효과 클래스에 대한 자세한 내용은 효과에서 이벤트 호출을 참조 하세요.

모든 플랫폼에서 TouchEffect 클래스에는 인수가 필요한 다음 생성자가 있습니다 ILogger .

public TouchEffect(ILogger logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

모든 플랫폼에서 종속성 주입 컨테이너에 대한 형식 등록은 메서드에 의해 RegisterTypes 수행되며, 이 메서드는 플랫폼이 메서드를 사용하여 LoadApplication(new App()) 애플리케이션을 로드하기 전에 호출됩니다. 다음 예제에서는 Android 플랫폼의 RegisterTypes 메서드를 보여줍니다.

void RegisterTypes()
{
    App.RegisterType<ILogger, Logger>();
    App.RegisterType<TouchTracking.Droid.TouchEffect>();
    App.BuildContainer();
}

이 예제 Logger 에서 구체적인 형식은 인터페이스 형식에 대한 매핑을 통해 등록되고 TouchEffect 형식은 인터페이스 매핑 없이 직접 등록됩니다. 사용자가 연결된 인스턴스가 포함된 BoxView 페이지로 이동하면 종속성 주입 컨테이너에서 플랫폼 TouchEffect 형식을 확인하기 위해 종속성 확인 메서드가 호출되며, 이 메서드는 형식 TouchEffect 을 확인하고 생성자에 삽입 LoggerTouchEffect 합니다.

DependencyService 구현 등록

샘플 애플리케이션에는 사용자가 디바이스의 사진 라이브러리에서 사진을 선택할 수 있도록 각 플랫폼의 구현을 사용하는 DependencyService 페이지가 포함되어 있습니다. 인터페이스는 IPhotoPicker 구현에 의해 DependencyService 구현되는 기능을 정의하며 다음 예제에 나와 있습니다.

public interface IPhotoPicker
{
    Task<Stream> GetImageStreamAsync();
}

각 플랫폼 프로젝트에서 클래스는 PhotoPicker 플랫폼 API를 IPhotoPicker 사용하여 인터페이스를 구현합니다. 이러한 종속성 서비스에 대한 자세한 내용은 그림 라이브러리에서 사진 선택(Picking a photo)을 참조 하세요.

iOS 및 UWP에서 PhotoPicker 클래스에는 인수가 필요한 다음 생성자가 있습니다 ILogger .

public PhotoPicker(ILogger logger)
{
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

모든 플랫폼에서 종속성 주입 컨테이너에 대한 형식 등록은 메서드에 의해 RegisterTypes 수행되며, 이 메서드는 플랫폼이 메서드를 사용하여 LoadApplication(new App()) 애플리케이션을 로드하기 전에 호출됩니다. 다음 예제에서는 UWP의 RegisterTypes 메서드를 보여줍니다.

void RegisterTypes()
{
    DIContainerDemo.App.RegisterType<ILogger, Logger>();
    DIContainerDemo.App.RegisterType<IPhotoPicker, Services.UWP.PhotoPicker>();
    DIContainerDemo.App.BuildContainer();
}

이 예제 Logger 에서는 구체적인 형식이 인터페이스 형식에 대한 매핑을 통해 등록되고 PhotoPicker 인터페이스 매핑을 통해 형식도 등록됩니다.

PhotoPicker Android 플랫폼의 생성자는 인수 외 ILogger 에 인수가 Context 필요하므로 약간 더 복잡합니다.

public PhotoPicker(Context context, ILogger logger)
{
    _context = context ?? throw new ArgumentNullException(nameof(context));
    _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

다음 예제에서는 Android 플랫폼의 RegisterTypes 메서드를 보여줍니다.

void RegisterTypes()
{
    App.RegisterType<ILogger, Logger>();
    App.RegisterTypeWithParameters<IPhotoPicker, Services.Droid.PhotoPicker>(typeof(Android.Content.Context), this, typeof(ILogger), "logger");
    App.BuildContainer();
}

이 예제에서 메서드는 App.RegisterTypeWithParameters 종속성 주입 컨테이너에 등록합니다 PhotoPicker . 등록 방법을 사용하면 인스턴스가 MainActivity 인수로 Context 삽입되고 형식이 Logger 인수로 ILogger 삽입됩니다.

사용자가 사진 선택 페이지로 이동하고 사진을 OnSelectPhotoButtonClicked 선택하도록 선택하면 처리기가 실행됩니다.

async void OnSelectPhotoButtonClicked(object sender, EventArgs e)
{
    ...
    var photoPickerService = DependencyService.Resolve<IPhotoPicker>();
    var stream = await photoPickerService.GetImageStreamAsync();
    if (stream != null)
    {
        image.Source = ImageSource.FromStream(() => stream);
    }
    ...
}

메서드가 DependencyService.Resolve<T> 호출되면 종속성 주입 컨테이너에서 형식을 확인하기 PhotoPicker 위해 종속성 확인 메서드가 호출되며, 이 메서드는 생성자에 형식 PhotoPicker 을 확인하고 삽입 Logger 합니다.

참고 항목

메서드를 Resolve<T> 통해 DependencyService애플리케이션의 종속성 주입 컨테이너에서 형식을 확인할 때 사용 해야 합니다.