xamarin 形式的跨平台移动应用程序(iOS、Android)中的依赖注入

Posted

技术标签:

【中文标题】xamarin 形式的跨平台移动应用程序(iOS、Android)中的依赖注入【英文标题】:Dependency Injection in a xamarin forms cross platform mobile app (iOS, Android) 【发布时间】:2021-11-10 14:37:27 【问题描述】:

我目前正在尝试使用 Microsoft.Extensions.DependencyInjection 库将依赖注入集成到我的 xamarin 表单跨平台移动应用程序中。我能够在我的共享项目中注册我的服务和视图模型,但我不确定如何注册在平台特定项目中实现的服务。例如,我有一个通过特定于平台的代码实现的接口 (IAuthenticationService),因此它在我的 androidios 项目中都有实现,但我不确定如何在我的容器中注册它以便使用正确的实现基于当前运行平台。这就是我在共享项目的启动类中设置 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() 来初始化包含所有服务和视图模型的容器:

public partial class App : Application

    public App()
                
        InitializeComponent();

        Startup.Init();

        MainPage = new AppShell();
    

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

    IStartViewModel _vM;

    public StartPage()
    
        InitializeComponent();

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

        BindingContext = _vM;
    

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

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

【问题讨论】:

【参考方案1】:

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

在所有平台上,依赖注入容器的类型注册都是通过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&lt;T&gt;,将调用依赖解析方法从依赖注入容器中解析PhotoPicker类型,这也将解析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);
    
    ...

【讨论】:

以上是关于xamarin 形式的跨平台移动应用程序(iOS、Android)中的依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

创建 xamarin 跨平台移动应用程序(android、ios 和 windows)的步骤

微软收购跨平台移动应用开发商Xamarin

微软收购跨平台移动应用开发商Xamarin

Xamarin移动开发的优点和缺点

Xamarin形式:Android和Windows平台上的HTML数据转换

移动UI控件Telerik UI for Xamarin发布R2 2019|引入Map控件