如何使用 IServiceProvider(一个具有不可空字段和异步初始化的类)来组合 DI?

问题描述 投票:0回答:1

想象一下我在 WPF 解决方案中有这样一个类:

public class TestClass
{
    private string _stringValue;
    private Database _database;
    
    public TestClass(Database database)
    {
        _database = database;
    }
    
    public async Task DoWork()
    {
        // do some async work involving _stringValue here
        // value of _stringValue comes from async database query
    }
}

构造函数参数通过以下代码由

IServiceProvider
中的
App.xaml.cs
解析:

private IServiceProvider CreateServiceProvider()
{
    return new ServiceCollection()
        .AddSingleton<IDatabase, Database>()
        .AddTransient(s => new TestClass(s.GetRequiredService<IDatabase>()))
        .BuildServiceProvider();
}

初始化和使用

TestClass
中的字段的最佳实践是什么?

到目前为止我正在这样做:

  • _stringValue
    设为可空
    string?
    ,将其初始化为
    string.Empty
    ,覆盖未使用的值并始终将其用作
    _stringValue!
  • 创建一个
    InitAsync()
    方法,在构建
    protected override async void OnStartup(StartupEventArgs e)
    时从
    App.xaml.cs
    中一个丑陋的
    IServiceProider
    调用它来查询数据库,希望我的同事不要忘记

我是否错过了更好的方法?

c# asynchronous dependency-injection
1个回答
0
投票

我编写这个小演示是为了让您找到正确的方向。 db 调用必须是同步的,但仅在第一次访问选项时发生(您可以在启动时访问它或使用

DataAnnotations
扩展来急切地加载值)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

var services = new ServiceCollection();

services.AddTransient<A>();
services.Configure<AOptions>(x => x.Config = Db.LoadConfig());

var provider = services.BuildServiceProvider();

Console.WriteLine("Finished building ServiceProvider.");

var a1 = provider.GetRequiredService<A>();

a1.PrintConfig();

var a2 = provider.GetRequiredService<A>();

a2.PrintConfig();

var a3 = provider.GetRequiredService<A>();

a3.PrintConfig();


class A
{
    private readonly int _config;
    public A(IOptions<AOptions> options)
    {
        _config = options.Value.Config;
    }

    public void PrintConfig() => Console.WriteLine($"_config is {_config}");
}
class AOptions
{
    public int Config { get; set; }
}

class Db
{
    public static int LoadConfig()
    {
        Console.WriteLine("Loaded config from database.");
        return 10;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.