c# - xamarin 表单跨平台移动应用程序(iOS、Android)中的依赖注入(inject)

标签 c# android ios xamarin dependency-injection

我目前正在尝试使用 Microsoft.Extensions.DependencyInjection 库将依赖项注入(inject)集成到我的 xamarin forms 跨平台移动应用程序中。我能够在共享项目中注册我的服务和 View 模型,但我不确定如何注册在特定于平台的项目中实现的服务。例如,我有一个接口(interface) (IAuthenticationService),它是通过特定于平台的代码实现的,因此它在我的 Android 和 iOS 项目中都有实现,但我不确定如何将其注册到我的容器中,以便使用正确的实现基于当前运行平台。这是我在共享项目的启动类中设置 DI 容器的方法:

public static class Startup
{
    public static IServiceProvider ServiceProvider { get; set; }

    public static IServiceProvider Init()
    {
        // Initialize all viewmodels and services with DI container
        var serviceProvider = new ServiceCollection().ConfigureServices().ConfigureViewModels().BuildServiceProvider();

        ServiceProvider = serviceProvider;

        return serviceProvider;
    }
}

public static class DependencyInjectionContainer
{
    
    public static IServiceCollection ConfigureServices(this IServiceCollection InServices)
    {
        //InServices.AddSingleton<IAuthenticationService>();
        InServices.AddSingleton<ISystemLayoutModel, SystemLayoutModel>();

        return InServices;
    }

    public static IServiceCollection ConfigureViewModels(this IServiceCollection InServices)
    {
        InServices.AddTransient<LoginViewModel>();
        InServices.AddTransient<StartViewModel>();
        InServices.AddTransient<RegistrationViewModel>();
        //All other viewmodels

        return InServices;
    }
}

我在 App.xaml.cs 中调用 Init() 来初始化包含所有服务和 View 模型的容器:

public partial class App : Application
{
    public App()
    {            
        InitializeComponent();

        Startup.Init();

        MainPage = new AppShell();
    }
}

每次我想将依赖项注入(inject)到我的 View 模型中时,我都会在后面的 View 代码中执行类似的操作

    IStartViewModel _vM;

    public StartPage()
    {
        InitializeComponent();

        _vM = Startup.ServiceProvider.GetService<StartViewModel>();

        BindingContext = _vM;
    }

下面的 View 模型看起来像这样:

class StartViewModel : ViewModelBase, IStartViewModel
{
    protected ISystemLayoutModel _LayoutModel;

    public StartViewModel(ISystemLayoutModel InSystemLayoutModel)
    {
        _LayoutModel = InSystemLayoutModel;

        LoadItemsForStart();

        if (_LayoutModel.SystemStartLayoutScreen.StartScreenTypes.Count < 1)
        {
            // Shutdown the application if it is not startup properly
            Application.Current.Quit();
        }
    }
    // More code
}

最佳答案

Official docs展示了如何注册 DependencyService 实现。

界面

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

Android 实现(构造函数)

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

在所有平台上,依赖注入(inject)容器的类型注册都是由 RegisterTypes 执行的。方法,在平台使用 LoadApplication(new App()) 加载应用程序之前调用该方法方法。

Android 示例

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

调用DependencyService.Resolve<T>某处,将调用依赖解析方法来解析 PhotoPicker从依赖注入(inject)容器中输入,这也将解析并注入(inject) Logger输入PhotoPicker构造函数。

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

关于c# - xamarin 表单跨平台移动应用程序(iOS、Android)中的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69194243/

相关文章:

c# - 如何保持连续流 - Tweetinvi

c# - 动态改变lambda表达式的主体?

android - 如何在项目单击时从 FirebaseListAdapter 获取 obj 键。 Firebase用户界面

ios - SKTexture 获取图像名称

ios - 以编程方式创建具有多个标签的 UIView

c# - 比较两个以逗号分隔的字符串是否匹配的最短代码是什么?

c# - 更改框架源 Wpf

ios - 总体设计——我应该在哪里放置集中访问的对象

Android Studio 构建失败,因为它无法合并 Renderscript 文件

android - 具有附近连接的最大连接端点数