es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Configure todas las opciones derivadas de la clase base de opciones o la interfaz .NET Core.

Tengo un código con variables en el archivo appsettings.json, así que registro todas las opciones en IServiceCollection a través del método configure:

public static void Configure(IServiceCollection services, IConfiguration configuration, bool useHangfire = true)
{
    services
        .Configure<authsettings>(configuration.GetSection(AuthSettings.SectionName))
        .Configure<cachesettings>(configuration.GetSection(CacheSettings.SectionName))
..... y así sucesivamente

Me gustaría crear una clase base (abstracta) o una interfaz, por ejemplo:

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; }
}

y configurar todas las opciones de esta manera:

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);
}

Ya he hecho lo mismo con el registro de trabajos Hangfire, pero este caso parece un poco diferente. Desafortunadamente, esta versión no funciona porque “currentSetting” debe implementar “IConfigureOptions“, pero no lo hace. También no estoy seguro de que este código obtenga los valores de JSON. ¿Alguien ha hecho algo similar?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en informática especializado en c#, asp.net y dependency-injection, puedo sugerir lo siguiente:

    Para crear una clase base abstracta o una interfaz para la configuración de ajustes, puedes definir una interfaz ISettings con una constante estática SectionName. Luego, puedes definir implementaciones para ajustes específicos, como AuthSettings, que contiene propiedades específicas e hereda de la interfazISettings.

    Para registrar todos los ajustes con IServiceCollection usando el método Configure, puedes usar un bucle foreach para recorrer todos los tipos en el ensamblado que implementan ISettings. Luego, puedes crear una instancia de cada tipo y usar el método ConfigureOptions para registrarlos con IServiceCollection.

    Sin embargo, ten en cuenta que la versión actual del código tiene algunos problemas. La interfaz ISettings no implementa IConfigureOptions <toptions>, que es necesario para registrar los ajustes usando el método ConfigureOptions. Además, falta el código para recuperar los valores del archivo JSON.

    Para solucionar estos problemas, la interfaz ISettings puede heredar de IConfigureOptions <toptions> e implementar el método Configure para recuperar los valores del archivo JSON. Luego, puedes modificar el bucle foreach para usar ActivatorUtilities.CreateInstance para crear instancias de los tipos de configuración concretos y pasar el objeto IConfiguration al constructor.

    Aquí hay un ejemplo de cómo se podría implementar:

    public interface ISettings<toptions> : IConfigureOptions<toptions>
        where TOptions : class
    {
        string SectionName { get; }
    }
    
    public class AuthSettings : ISettings<authsettingsoptions>
    {
        public const string SectionName = "AuthSettings";
    
        public int ConfirmCodeLength { get; set; }
        public string AllowedChars { get; set; }
        public TimeSpan ConfirmCodeExpiry { get; set; }
    
        public void Configure(AuthSettingsOptions options)
        {
            options.ConfirmCodeLength = ConfirmCodeLength;
            options.AllowedChars = AllowedChars;
            options.ConfirmCodeExpiry = ConfirmCodeExpiry;
        }
    }
    
    public class SettingsConfigurator
    {
        public static void Configure(IServiceCollection services, IConfiguration configuration)
        {
            var settingsTypes = Assembly.GetExecutingAssembly().GetTypes()
                .Where(t => typeof(ISettings<>).IsAssignableFrom(t) && !t.IsAbstract);
    
            foreach (var settingsType in settingsTypes)
            {
                var optionsType = settingsType.BaseType.GetGenericArguments()[0];
                var sectionName = (string)settingsType.GetProperty("SectionName").GetValue(null);
                var configureOptionsMethod = typeof(OptionsConfigurationServiceCollectionExtensions)
                    .GetMethod("Configure", new[] { typeof(IServiceCollection), typeof(Action<>).MakeGenericType(optionsType) });
    
                var createInstanceMethod = typeof(ActivatorUtilities)
                    .GetMethod("CreateInstance", new[] { typeof(IServiceProvider), typeof(Type), typeof(object[]) });
    
                var instance = createInstanceMethod.Invoke(null, new object[] { services.BuildServiceProvider(), settingsType, new object[] { } });
    
                configureOptionsMethod.Invoke(null, new[] { services, instance });
            }
        }
    }
    

    En el método Configure, cada clase de configuración puede poblar el objeto de opciones con los valores del archivo de configuración. La clase SettingsConfigurator usa reflexión para recuperar los tipos que implementan ISettings<toptions>, y luego usaActivatorUtilities para crear instancias de cada tipo con el objeto IConfiguration pasado al constructor. Finalmente, registra cada objeto de configuración con IServiceCollection utilizando el método Configure.

    Usando este enfoque, puedes definir una clase base abstracta o una interfaz para la configuración de ajustes, y registrar fácilmente todos los ajustes con IServiceCollection sin tener que registrar manualmente cada clase de ajuste por separado.

Comments are closed.