如何根据应用程序设置使用不同的模块?

How can I use different modules based on application settings?

我是 asp.net 核心的新手,我想在 asp.net 核心网络 API 启动期间设置 属性 值。 数据是从数据库中获取的,我需要整个应用程序的值,它应该只被调用一次。

我的项目中有两种状态,假设它是 A 和 B。在 A 中显示了一组项目,在 B 中显示了不同的项目。我从数据库中获取应用程序设置数据,并根据该数据在整个应用程序生命周期中显示 A 模块或 B 模块。

此问题的一般解决方案是配置一个要在 ServiceCollection 中注册的单例对象。

services.AddSingleton<ISingletonObject, SingletonObject>();

此类对象的构造函数将加载必要的数据,然后使用构造函数注入将单例对象加载到每个 class(例如控制器)。

public class SomeController(ISingletonObject singletonObject)
{
     // singleton object will be injected with it's pre-loaded data available   
}

对象 SingletonObject 的构造函数将只执行一次,无论它被服务集合注入了多少其他构造函数。

.NET 中没有全局变量,更不用说 C# 了。将配置数据存储在全局静态属性中不是一个好主意,因为它将您的代码与保存这些属性的静态 class 联系在一起,使编写或测试代码变得更加困难。

配置中间件

ASP.NET Core 通过配置中间件解决了这个问题,它可以从多个提供程序读取配置设置,包括文件、数据库甚至 in-memory 集合。 Configuration overview article 展示了如何使用字典作为配置源:

var builder = WebApplication.CreateBuilder(args);

var Dict = new Dictionary<string, string>
        {
           {"MyKey", "Dictionary MyKey Value"},
           {"Position:Title", "Dictionary_Title"},
           {"Position:Name", "Dictionary_Name" },
           {"Logging:LogLevel:Default", "Warning"}
        };

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.Sources.Clear();

    config.AddInMemoryCollection(Dict);

    config.AddEnvironmentVariables();

    if (args != null)
    {
        config.AddCommandLine(args);
    }
});

builder.Services.AddRazorPages();

var app = builder.Build();

之后,所有 classes 都可以通过 IConfiguration 接口检索配置值,无论它们来自何处:

public class TestModel : PageModel
{
    // requires using Microsoft.Extensions.Configuration;
    private readonly IConfiguration Configuration;

    public TestModel(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public ContentResult OnGet()
    {
        var myKeyValue = Configuration["MyKey"];
        var title = Configuration["Position:Title"];
        var name = Configuration["Position:Name"];
        var defaultLogLevel = Configuration["Logging:LogLevel:Default"];


        return Content($"MyKey value: {myKeyValue} \n" +
                       $"Title: {title} \n" +
                       $"Name: {name} \n" +
                       $"Default Log Level: {defaultLogLevel}");
    }
}

在您的情况下,您可以从数据库加载设置并将它们注册为 Program.cs 中的 in-memory 源:

var Dict=LoadDataAsDictionary();
...
    config.AddInMemoryCollection(Dict);
...

依赖注入中间件

另一种选择是将数据加载为强类型对象,并使用依赖注入中间件将其注册为 Signleton 实例:

var builder = WebApplication.CreateBuilder(args);

MyCacheData cacheData=LoadStronglyTypedData();

builder.Services.AddSingleton(cachedata);

这个 class 可以像其他 DI 服务或 IConfiguration 一样注入到页面和控制器中:

public class TestModel : PageModel
{

    private readonly MyCacheData Data;

    public TestModel(MyCacheData data)
    {
        Data = data;
    }