配置从基本选项 class 或接口 .NET Core 派生的所有选项

Configure all options derived from base option class or interface .NET Core

我在 appsettings.json 文件中有带变量的代码,所以我通过配置方法在 IServiceCollection 中注册了所有选项:

public static void Configure(IServiceCollection services, IConfiguration configuration, bool useHangfire = true)
        {
            services
                .Configure<AuthSettings>(configuration.GetSection(AuthSettings.SectionName))
                .Configure<CacheSettings>(configuration.GetSection(CacheSettings.SectionName))
..... and so on

我想创建一个基础(抽象)class 或接口,例如

public interface ISettings
    {
        public const string SectionName = "DefaultSettings";
    }
public class AuthSettings: ISettings
    {
        public const string SectionName = "AuthSettings";

        public int ConfirmCodeLength { get; set; }
        public string AllowedChars { get; set; }
        public TimeSpan ConfirmCodeExpiry { get; set; }
}

并像这样配置所有设置

foreach (var type in
                Assembly.GetAssembly(typeof(ISettings)).GetTypes()
                    .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(ISettings))))
            {
                var currentSettings = (ISettings)Activator.CreateInstance(type);
                services.ConfigureOptions(currentSettings);
            }

我已经对 hangfire 作业的注册做了同样的事情,但这个案例看起来有点不同。 不幸的是,这个版本不起作用,因为 currentSetting 应该实现 IConfigureOptions 但它没有。此外,我不确定此代码是否从 JSON 获取值。 有人做过这样的事吗?

因此,如果您有很多设置,您可以为所有设置创建基础 class,它具有定义部分名称的方法

public class BaseSettings
{
    public virtual string SectionName => this.GetType().Name;
}

很多settings-classes喜欢这样

public class AuthSettings:BaseSettings
{
    public int ConfirmCodeLength { get; set; }
    public string AllowedChars { get; set; }
    public TimeSpan ConfirmCodeExpiry { get; set; }
}

然后在 ServiceCollection 扩展 class set 方法中找到所有继承的 classes 并将其添加到 IServiceCollection

public static IServiceCollection AddAllOptions(this IServiceCollection services, IConfiguration configuration)
    {
        foreach (var type in
            Assembly.GetAssembly(typeof(BaseSettings)).GetTypes()
                .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(BaseSettings))))
        {
            var configurationInstance = (BaseSettings)Activator.CreateInstance(type);
            if (configurationInstance != null)
            {
                var configurationSection = configuration.GetSection(configurationInstance.SectionName);
                var configureMethod = typeof(OptionsConfigurationServiceCollectionExtensions).GetMethods()
                    .Where(x => x.Name == "Configure")
                    .Single(m => m.GetParameters().Length == 2)
                    .MakeGenericMethod(type);
                configureMethod.Invoke(null, new object[] { services, configurationSection });
            }
        }

        return services;
    }

你终于可以在你的StartUp中使用这个方法了class

service.AddAllOptions(configuration);