使用带有IServiceProvider的xamarin表单

Nev*_*ane 6 architecture dependency-injection service-provider xamarin.forms

我正在研究xamarin表单上的"依赖注入",并发现了一些使用类似的概念ContainerBuilder.在线发现的解决方案就是这样,讨论如何进行DI设置并将它们注入到视图模型中.但是,就个人而言,我没有发现这个或整个概念的视图模型和绑定非常整齐有几个原因.我宁愿创建可以被业务逻辑重用的服务,这似乎使代码更加清晰.我觉得实施一个IServiceProvider会导致更清洁的实施.我计划实现这样的服务提供商:

IServiceProvider Provider = new ServiceCollection()
                            .AddSingleton<OtherClass>()
                            .AddSingleton<MyClass>()
                            .BuildServiceProvider();
Run Code Online (Sandbox Code Playgroud)

首先,我不确定为什么没有这些的xamarin例子.所以,我不确定朝着这个方向走向是否有任何问题.我已经看过ServiceCollection课了.它来自的包Microsoft.Extensions.DependencyInjection,名称中没有"aspnetcore".然而,它的拥有者是"aspnet".我不完全确定它ServiceCollection是否仅适用于Web应用程序,或者将它用于移动应用程序是否有意义.

它是安全使用IServiceProviderServiceCollection只要我使用所有的单身?我有什么问题(在表现或公羊方面)我不知道了吗?

更新

在Nkosi的评论之后,我又看了一下链接并发现了一些事情:

  1. 文档链接大约在同一时间Microsoft.Extensions.DependencyInjection仍处于测试阶段
  2. 在文档中的"使用依赖注入容器的几个优点"下的列表中的所有点也适用于DependencyInjection我所见.
  3. Autofac 过程似乎围绕着我试图避免使用的ViewModels.

更新2

我设法在导航功能的帮助下将DI直接导入到后面的页面代码中,如下所示:

public static async Task<TPage> NavigateAsync<TPage>()
    where TPage : Page
{
    var scope = Provider.CreateScope();
    var scopeProvider = scope.ServiceProvider;
    var page = scopeProvider.GetService<TPage>();
    if (navigation != null) await navigation.PushAsync(page);
    return page;
}
Run Code Online (Sandbox Code Playgroud)

Mou*_*ars 4

此实现使用Splat和一些帮助器/包装器类来方便地访问容器。

服务的注册方式有点冗长,但它可以涵盖我迄今为止遇到的所有用例;并且生命周期也可以很容易地改变,例如切换到服务的延迟创建。

只需使用ServiceProvider类即可从代码中任意位置的 IoC 容器检索任何实例。

注册您的服务

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        SetupBootstrapper(Locator.CurrentMutable);
        MainPage = new MainPage();
    }

    private void SetupBootstrapper(IMutableDependencyResolver resolver)
    {
        resolver.RegisterConstant(new Service(), typeof(IService));
        resolver.RegisterLazySingleton(() => new LazyService(), typeof(ILazyService));
        resolver.RegisterLazySingleton(() => new LazyServiceWithDI(
            ServiceProvider.Get<IService>()), typeof(ILazyServiceWithDI));
        // and so on ....
    }
Run Code Online (Sandbox Code Playgroud)

服务提供商的使用

// get a new service instance with every call
var brandNewService = ServiceProvider.Get<IService>();

// get a deferred created singleton
var sameOldService = ServiceProvider.Get<ILazyService>();

// get a service which uses DI in its contructor
var another service = ServiceProvider.Get<ILazyServiceWithDI>();
Run Code Online (Sandbox Code Playgroud)

ServiceProvider的实现

public static class ServiceProvider
{
    public static T Get<T>(string contract = null)
    {
        T service = Locator.Current.GetService<T>(contract);
        if (service == null) throw new Exception($"IoC returned null for type '{typeof(T).Name}'.");
        return service;
    }

    public static IEnumerable<T> GetAll<T>(string contract = null)
    {
        bool IsEmpty(IEnumerable<T> collection)
        {
            return collection is null || !collection.Any();
        }

        IEnumerable<T> services = Locator.Current.GetServices<T>(contract).ToList();
        if (IsEmpty(services)) throw new Exception($"IoC returned null or empty collection for type '{typeof(T).Name}'.");

        return services;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的 csproj 文件。没什么特别的,我添加的唯一 nuget 包是 Spat

共享项目 csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <ProduceReferenceAssembly>true</ProduceReferenceAssembly>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DebugType>portable</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Splat" Version="9.3.11" />
    <PackageReference Include="Xamarin.Forms" Version="4.3.0.908675" />
    <PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
  </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)