首页 > 解决方案 > 库如何知道消费者是否实现了库接口并将其注册到 DI 容器中?

问题描述

我正在学习 Xamarin.Forms 并尝试在以下场景中使用 DI。

共享项目(或库)有一个与 DI 相关的类,如下所示。

public static class Startup
{
    public static ServiceProvider CreateServiceProvider(Action<IServiceCollection> nativeConfigureServices)
    {
        IServiceCollection isc = new ServiceCollection();

        nativeConfigureServices(isc);
        ConfigureServices(isc);

        return isc.BuildServiceProvider();
    }


    static void ConfigureServices(IServiceCollection isc)
    {
        // others services are omitted for the sake of simplicity
        isc.AddTransient<MainPageViewModel>();
        isc.AddTransient<MainPage>();
        isc.AddSingleton<App>();
    }
}

INativeCall是一个可以由消费者选择实现的接口。

public interface INativeCall
{
    Task FloatMessage(string msg);
}

的一个实例INativeCall被注入 MainPage如下。

public partial class MainPage : ContentPage
{
    private readonly INativeCall nativeCall;

    public MainPage(MainPageViewModel vm, INativeCall nativeCall)
    {
        InitializeComponent();

        // others are omitted for the sake of simplicity
        this.nativeCall = nativeCall;
    }


    private void Greeting_Clicked(object sender, System.EventArgs e)
    {
        nativeCall?.FloatMessage("I Love Xamarin.Forms");
    }
}

然后其他特定于操作系统的项目(Android、UWP、iOS)可以INativeCall通过nativeConfigureServices.

为了简单起见,我选择一个Android项目如下。

public class NativeCall : INativeCall
{
    public async Task FloatMessage(string msg)
    {
        Toast.MakeText(Application.Context, msg, ToastLength.Long).Show();
        await Task.CompletedTask;
    }
}

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        // others have been removed for simplicity 

        ServiceProvider sp = Startup.CreateServiceProvider(isc =>
        {
            isc.AddSingleton<INativeCall, NativeCall>();
        });

        LoadApplication(sp.GetRequiredService<App>());
    }
}

问题

如果消费者(上面的Android项目)既没有实现INativeCall也没有在DI容器中注册它,我该如何修改

private void Greeting_Clicked(object sender, System.EventArgs e)
{
    nativeCall?.FloatMessage("I Love Xamarin.Forms");
}

摆脱运行时错误?

System.InvalidOperationException:“尝试激活“MainPage”时,无法解析“INativeCall”类型的服务。

换句话说,库如何知道消费者是否实现了库接口并将其注册到 DI 容器中?

标签: c#xamarin

解决方案


System.InvalidOperationException:“尝试激活“MainPage”时,无法解析“INativeCall”类型的服务。

这是指示MainPage具有无法满足的构造函数依赖项的容器。

最简单的解决方案通常是更改:

public MainPage(MainPageViewModel vm, INativeCall nativeCall)

至:

public MainPage(MainPageViewModel vm, INativeCall nativeCall = null)

表示依赖项是可选的。

这将要求nativeCall类中的所有用法都进行null检查(因为nativeCall可能已提供或未提供)。就像你已经在做nativeCall?.FloatMessage("I Love Xamarin.Forms");


推荐阅读