前言

最近有点忙,学习有点懈怠(惭愧),抽时间学习把这篇博客写完,希望理解。相信自己能坚持下去,把这个系列写完。好啦,开搞。说道配置文件,基本大多数软件为了扩展性、灵活性都会涉及到配置文件,比如之前常见的app.config和web.config。然后再说.NET Core,很多都发生了变化。总体的来说技术在进步,新的方式更加轻量级,具有更好的扩展性,数据源更加多样性。

ASP.NET Core 应用可用的配置提供程序

GetSection

IConfiguration.GetSection 会返回具有指定子节键的配置子节。

GetChildren

IConfiguration.GetChildren 方法获取直接后代配置子节。

Exists

ConfigurationExtensions.Exists(IConfigurationSection)确定该部分是否具有 Value 或子级。

将配置绑定到对象

新建ASP.NET Core Web API项目,在主目录下添加MyArray.json文件。

{
  "array": {
    "entries": {
      "0": "value0",
      "1": "value1",
      "2": "value2",
      "3": "value3"
    }
  }
}

创建一个model。

    public class Model
    {
        public string[] Entries { get; set; }
    }

在Program类中读取配置文件

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
               config.Sources.Clear();
               var env = hostingContext.HostingEnvironment;
               config.AddJsonFile("MyArray.json",optional: true,reloadOnChange: true);
               config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

新建一个名为SettingsController的控制器,读取配置文件。

    [Route("api/[controller]/[action]")]
    [ApiController]
    public class SettingsController : ControllerBase
    {
        private readonly IConfiguration Configuration;
        public SettingsController(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public ContentResult ToModel()
        {
        array = Configuration.GetSection("array").Get<Model>();
            string modelStr = null;
            for (int j = 0; j < array.Entries.Length; j++)
            {
                modelStr += $"Index: {j}  Value:  {array.Entries[j]} \n";
            }

            return Content(modelStr);
        }
    }

利用PostMan可以看到已经读取到绑定到Model的配置。
ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置-LMLPHP

自定义配置

如果上面的方式还不能满足项目要求的话,还可以从数据库中读取配置信息。接下来我们通过实体框架(EF)读取数据库中配置信息(埋个伏笔,后续做个相关教程)。便于操作,这次使用内存数据库做配置源。
首先做一个创建一个实体。

    public class EFModel
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Value { get; set; }
    }

添加 EFConfigContext 以存储和访问配置的值。

    public class EFConfigContext:DbContext
    {
        public EFConfigContext(DbContextOptions options) : base(options)
        {
        }

        public DbSet<EFModel> Values { get; set; }
    }

创建用于实现 IConfigurationSource 的类。

    public class EFConfigurationSource : IConfigurationSource
    {
        private readonly Action<DbContextOptionsBuilder> _optionsAction;

        public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
        {
            _optionsAction = optionsAction;
        }

        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new EFConfigurationProvider(_optionsAction);
        }
    }

通过从 ConfigurationProvider 继承来创建自定义配置提供程序。 当数据库为空时,配置提供程序将对其进行初始化。

    public class EFConfigurationProvider:ConfigurationProvider
    {
        Action<DbContextOptionsBuilder> OptionsAction { get; }
        public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
        {
            OptionsAction = optionsAction;
        }

        public override void Load()
        {
            var builder = new DbContextOptionsBuilder<EFConfigContext>();

            OptionsAction(builder);

            using (var dbContext =new EFConfigContext(builder.Options))
            {
                dbContext.Database.EnsureCreated();

                Data =!dbContext.Values.Any()?CreateAndSaveValues(dbContext) : dbContext.Values.ToDictionary(c => c.Name, c => c.Value);
            }

        }

        private static IDictionary<string, string> CreateAndSaveValues(EFConfigContext dbContext)
        {
            var configValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
            {
                {"name1","value1" },
                {"name2","value2" },
                {"name3","value3" }
            };

            dbContext.Values.AddRange(configValues.Select(v => new EFModel
            {
                Name = v.Key,
                Value = v.Value
            }).ToArray());

            dbContext.SaveChanges();

            return configValues;
        }
    }

使用 AddEFConfiguration 扩展方法将配置源添加到 ConfigurationBuilder。

    public static class EFExtensions
    {
        public static IConfigurationBuilder AddEFConfiguration(this IConfigurationBuilder builder,Action<DbContextOptionsBuilder> optionsAction)
        {
            return builder.Add(new EFConfigurationSource(optionsAction));
        }
    }

在 Program.cs 中使用自定义的 EFConfigurationProvider:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.Sources.Clear();

                var env = hostingContext.HostingEnvironment;

                config.AddEFConfiguration(
                options => options.UseInMemoryDatabase("InMemoryDb"));


                config.AddEnvironmentVariables();

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
            })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

在Startup中通过依赖注入添加据库上下文服务,向控制器提供服务。

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<EFConfigContext>(opt => opt.UseInMemoryDatabase("InMemoryDb"));
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

在控制器中注入服务,读取内存数据库中的数据。

    [Route("api/[controller]/[action]")]
    [ApiController]
    public class SettingsController : ControllerBase
    {

        private readonly EFConfigContext _efDbContext;

        public SettingsController( EFConfigContext efDbContext)
        {
            _efDbContext = efDbContext;
        }


        public ActionResult<IEnumerable<EFModel>> EFSetting()
        {
            List<EFModel> list = _efDbContext.Values.ToList();

            return list;
        }
    }

利用PostMan可以看到已经读取到我们自定义的配置源。
ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置-LMLPHP
加一张整体的项目结构,方便大家理解。
ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置-LMLPHP
最近疫情有些反复,出门做好个人防护,玩耍时别忘记学习。最后祝大家周末愉快!

10-30 09:30