想象一下我在 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
调用它来查询数据库,希望我的同事不要忘记我是否错过了更好的方法?
我编写这个小演示是为了让您找到正确的方向。 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;
}
}