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

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

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
}

【问题讨论】:

    标签: c# android ios xamarin dependency-injection


    【解决方案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);
        }
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多