如何从 ASP.Net Core 配置文件合并多个数组?

2024-02-21

我想在我的应用程序中动态加载和注册服务。为此,我需要能够从解决方案中的不同项目加载配置文件,并将它们的值合并到单个 json 数组中。 不幸的是,默认情况下,ASP.Net Core 配置会覆盖值。

我使用以下代码注册文件(Program.cs 文件的一部分):

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((webHostBuilderContext, configurationbuilder) =>
            {
                var env = webHostBuilderContext.HostingEnvironment;
                configurationbuilder.SetBasePath(env.ContentRootPath);
                configurationbuilder.AddJsonFile("appsettings.json", false, true);

                var path = Path.Combine(env.ContentRootPath, "App_Config\\Include");

                foreach(var file in Directory.EnumerateFiles(path, "*.json",SearchOption.AllDirectories))
                {
                    configurationbuilder.AddJsonFile(file, false, true);
                }
                configurationbuilder.AddEnvironmentVariables();
            })
            .UseStartup<Startup>();

该代码搜索所有文件*.json内部延伸App_Config\Include目录并将它们全部添加到配置生成器中。

文件的结构如下所示:

{
  "ServicesConfiguration": {
    "Services": [
      {
        "AssemblyName": "ParsingEngine.ServicesConfigurator, ParsingEngine"
      }
    ]
  }
}

正如你所看到的,我有主要部分ServicesConfiguration then Services包含具有一个属性的对象的数组AssemblyName.

为了读取我使用的这些值ServicesConfiguration带有列表的类:

public class ServicesConfiguration
    {
        public List<ServiceAssembly> Services { get; set; }
    }

该列表使用ServiceAssembly class:

public class ServiceAssembly
    {
        public string AssemblyName { get; set; }
    }

为了加载我使用的配置IOptions在构造函数级别 (DI):

Microsoft.Extensions.Options.IOptions<ServicesConfiguration> servicesConfiguration,

配置似乎已加载 - 但文件中的值不会合并,而是被最后找到的文件覆盖。

有什么想法如何解决这个问题吗?


所以你知道我在评论中的意思,这是一个潜在的答案

由于您必须从不同的项目加载不同的“配置”文件并对它们应用一些合并逻辑,因此我会避免使用“默认”配置系统来加载JSON文件到应用程序中。相反,我会自己做。所以:

  1. 读取 JSON 并将其反序列化为类型并将其保留在列表中
  2. 浏览包含所有配置的列表并应用您的合并逻辑
  3. 注册单号ServicesConfiguration as a Singleton
  4. 删除您的代码Program.cs加载自定义JSON files

您可以这样做:

ServicesRootConfiguration(新类,能够反序列化json)

public class ServicesRootConfiguration
{
    public ServicesConfiguration ServicesConfiguration { get; set; }
}

Startup.cs

public class Startup
{
    private readonly IHostingEnvironment _hostingEnvironment;

    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        Configuration = configuration;
        _hostingEnvironment = env;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        // other configuration omitted for brevity

        // build your custom configuration from json files
        var myCustomConfig = BuildCustomConfiguration(_hostingEnvironment);

        // Register the configuration as a Singleton
        services.AddSingleton(myCustomConfig);
    }

    private static ServicesConfiguration BuildCustomConfiguration(IHostingEnvironment env)
    {
        var allConfigs = new List<ServicesRootConfiguration>();

        var path = Path.Combine(env.ContentRootPath, "App_Config");

        foreach (var file in Directory.EnumerateFiles(path, "*.json", SearchOption.AllDirectories))
        {
            var config = JsonConvert.DeserializeObject<ServicesRootConfiguration>(File.ReadAllText(file));
            allConfigs.Add(config);
        }

        // do your logic to "merge" the each config into a single ServicesConfiguration
        // here I simply select the AssemblyName from all files.
        var mergedConfig = new ServicesConfiguration
        {
            Services = allConfigs.SelectMany(c => c.ServicesConfiguration.Services).ToList()
        };

        return mergedConfig;
    }
}

然后在你的Controller通常只需通过 DI 获取实例即可。

public class HomeController : Controller
{
    private readonly ServicesConfiguration _config;

    public HomeController(ServicesConfiguration config)
    {
        _config = config ?? throw new ArgumentNullException(nameof(config));
    }
}

通过这种方法,您最终会获得与正常注册相同的行为IOptions。但是,您可以避免依赖它并不得不使用丑陋的.Value(呃)。更好的是,您可以将其注册为接口,以便在测试/模拟期间使您的生活更轻松。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 ASP.Net Core 配置文件合并多个数组? 的相关文章

随机推荐