NOTE: Apart from
(and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.
Friday, 27 September 2024
//Less than a minute
似乎每个人都有这个代码的版本, 我第一次见到这个方法, 菲利普 W 最近我的老同事菲尔·哈克 其版本.
仅仅为了完成,这是我如何做到的。
为何要让配置更容易操作? 此时此刻,第一 使用的方式正在使用 IOptions<T>
和 IOptionsSnapshot<T>
但它是一个有点 痛苦的工作。 这种方法可以让您以更自然的方式与配置合作。
限制在于你不能使用 IOptions<T>
样式,所以您无法在不重新启动应用程序的情况下重新装入配置 。 但老实说,这几乎是我从未想做的事。
在我的版本中,我使用最近的静态界面成员来具体说明,这一类的所有情况都必须宣布 Section
财产。 此选项用于从配置中获取区域 。
public interface IConfigSection {
public static abstract string Section { get; }
}
因此,对于每一项执行,你然后具体说明本部分应受下列约束的哪一节:
public class NewsletterConfig : IConfigSection
{
public static string Section => "Newsletter";
public string SchedulerServiceUrl { get; set; } = string.Empty;
public string AppHostUrl { get; set; } = string.Empty;
}
在此情况下,它正在寻找一个区域 在配置中被调用 Newsletter
.
"Newsletter": {
"SchedulerServiceUrl" : "http://localhost:5000",
"AppHostUrl" : "https://localhost:7240"
}
然后,我们将能够将这一点约束在 Program.cs
像这样的文件 :
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
services.ConfigurePOCO<NewsletterConfig>(config);
我们也可以从中获取配置值 Program.cs
像这样的文件 :
var newsletterConfig = services.ConfigurePOCO<NewsletterConfig>(config);
甚至为了 WebApplicationBuilder
类似 :
var newsletterConfig = builder.Configure<NewsletterConfig>();
注:由于建造者可以使用 ConfigurationManager
它不需要通过。
意思是您现在可以选择如何绑定配置 。
另一个好处是,如果你以后需要使用这些数值 Program.cs
然后,该对象可供您使用。
为了让这一切成为可能,我们有一个相当简单的扩展方法, 将配置与等级绑在一起。
以下代码允许:
// These get the values and bind them to the class while adding these to Singleton Scope
var newsletterConfig = services.ConfigurePOCO<NewsletterConfig>(config);
var newsletterConfig = services.ConfigurePOCO<NewsletterConfig>(configuration.GetSection(NewsletterConfig.Section));
// Or for Builder...These obviously only work for ASP.NET Core applications, take them out if you are using this in a different context.
var newsletterConfig = builder.Configure<NewsletterConfig>();
var newsletterConfig = builder.Configure<NewsletterConfig>(NewsletterConfig.Section);
// These just return a dictionary, which can be useful to get all the values in a section
var newsletterConfig = builder.GetConfigSection<NewsletterConfig>();
所有这一切都由以下扩展类启用 。
您可以看到它的主要动力是使用静态界面成员指定区域名称。 然后用它从配置中获取区域 。
namespace Mostlylucid.Shared.Config;
public static class ConfigExtensions {
public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfigurationSection configuration)
where TConfig : class, new() {
if (services == null) throw new ArgumentNullException(nameof(services));
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
var config = new TConfig();
configuration.Bind(config);
services.AddSingleton(config);
return config;
}
public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, ConfigurationManager configuration)
where TConfig : class, IConfigSection, new()
{
var sectionName = TConfig.Section;
var section = configuration.GetSection(sectionName);
return services.ConfigurePOCO<TConfig>(section);
}
public static TConfig Configure<TConfig>(this WebApplicationBuilder builder)
where TConfig : class, IConfigSection, new() {
var services = builder.Services;
var configuration = builder.Configuration;
var sectionName = TConfig.Section;
return services.ConfigurePOCO<TConfig>(configuration.GetSection(sectionName));
}
public static TConfig GetConfig<TConfig>(this WebApplicationBuilder builder)
where TConfig : class, IConfigSection, new() {
var configuration = builder.Configuration;
var sectionName = TConfig.Section;
var section = configuration.GetSection(sectionName).Get<TConfig>();
return section;
}
public static Dictionary<string, object> GetConfigSection(this IConfiguration configuration, string sectionName) {
var section = configuration.GetSection(sectionName);
var result = new Dictionary<string, object>();
foreach (var child in section.GetChildren()) {
var key = child.Key;
var value = child.Value;
result.Add(key, value);
}
return result;
}
public static Dictionary<string, object> GetConfigSection<TConfig>(this WebApplicationBuilder builder)
where TConfig : class, IConfigSection, new() {
var configuration = builder.Configuration;
var sectionName = TConfig.Section;
return configuration.GetConfigSection(sectionName);
}
}
使用这些很简单。 在任何需要这种配置的班级中,您都可以这样直接注射:
public class NewsletterService(NewsletterConfig config {
}
嗯,就是这样... 很简单... 但它是一个技术 我在所有项目中使用的技巧。 这是一个很好的方式 与配置工作 和我认为它 有点自然 比 IOptions<T>
模式。