Cómo no romper los límites, cómo crear una buena arquitectura y cómo hacer un buen mantenimiento

Settings por entorno en dotNet MAUI

Los pasos que sigo para conseguirlo, son los siguientes.

1. Crear configuraciones de solución

Desde el editor de configuración, añado una configuración por cada entorno, para Debug y Release, por lo que en el ejemplo, tendré 6 configuraciones: DebugDevelopment, ReleaseDevelopment, DebugPreproduction, ReleasePreproduction, Debug y Release, siendo Debug y Release los que utilizo como configuraciones de producción.

2. Crear configuraciones en los proyectos

En el ejemplo que estoy creando, solamente tengo un proyecto, pero si tuviese más, habría que repetir estos pasos para cada uno de los proyectos, siempre y cuando tengan funcionalidades que dependan del entorno en el que se están ejecutando. Si no es así, en esos proyecto no sería necesario añadir todas las configuraciones, con mantener Debug y Release, que son las creadas por defecto, sería suficiente.

Este ejemplo lo estoy creando con Rider, y este IDE crea automáticamente las configuraciones en todos los proyectos al crear las configuraciones de la solución. No obstante, desde cualquier IDE se pueden crear manualmente, incluso se pueden añadir editando el .csproj de cada proyecto, como se mostrará a continuación.

Una vez creadas estas configuraciones, el siguiente paso sería añadir una constante a cada una de las configuraciones. En mi ejemplo, he añadido las constantes DEVELOPMENT y PREPRODUCTION a sus respectivas configuraciones. Nótese que a las configuraciones de producción no les añado ninguna constante.

El .csproj del proyecto quedaría de la siguiente manera.

...
<PropertyGroup>
    ...
    <Configurations>Debug;Release;DebugDevelopment;DebugPreproduction;ReleaseDevelopment;ReleasePreproduction</Configurations>
    ...
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'DebugDevelopment' ">
  <DefineConstants>TRACE;DEVELOPMENT</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'DebugPreproduction' ">
  <DefineConstants>TRACE;PREPRODUCTION</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseDevelopment' ">
  <DefineConstants>TRACE;DEVELOPMENT</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'ReleasePreproduction' ">
  <DefineConstants>TRACE;PREPRODUCTION</DefineConstants>
</PropertyGroup>
...

Una vez creadas las configuraciones a nivel de solución y a nivel de proyecto, queda vincularlas. Tanto en Rider como en Visual Studio, se puede hacer de una forma sencilla con un editor visual.

3. Crear json de configuración

De forma análoga a lo que tenemos en asp.net, me gusta crear un json por cada entorno. Siguiendo con el ejemplo, mi proyecto quedaría de la manera que se muestra a continuación.

Además, para poder acceder a estos json en tiempo de ejecución, es importante que modifiquemos las propiedades de estos archivos para que sus build actions sean EmbeddedResource y sus copy to output directory sean Copy if newer.

4. Añadir información de los json a la configuración del proyecto

Desde la llegada de dotNet MAUI, podemos disfrutar del MauiAppBuilder, en el que definir fuentes, servicios y configuraciones, entre otros… Lo que vamos a conseguir con este paso, es añadir al Configuration de este builder, la información del json añadido en el paso anterior, dependiendo del entorno que estemos ejecutando. Para conseguirlo, añadimos la siguiente funcionalidad a la clase MauiProgram

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .AddCustomConfiguration()
            ...

        return builder.Build();
    }

    private static MauiAppBuilder AddCustomConfiguration(this MauiAppBuilder builder)
    {
        var executingAssembly = Assembly.GetExecutingAssembly();
        using var stream = executingAssembly.GetManifestResourceStream(GetEnvironmentSettings());
        var configuration = new ConfigurationBuilder()
            .AddJsonStream(stream)
            .Build();
        
        builder.Configuration.AddConfiguration(configuration);
        return builder;
    }

    private static string GetEnvironmentSettings()
    {
#if DEVELOPMENT
        return "MauiSettings.Settings.appsettings.Development.json";
#elif PREPRODUCTION
        return "MauiSettings.Settings.appsettings.Preproduction.json";
#else
        return "MauiSettings.Settings.appsettings.json";
#endif
    }
}

Es importante destacar que, para añadir la funcionalidad anterior, tenemos que añadir los siguientes paquetes nugets a nuestro proyecto.

  • Microsoft.Extensions.Configuration.Binder
  • Microsoft.Extensions.Configuration.Json

5. Usar settings

El último paso, sería saber cómo utilizar los settings que hemos creado. La forma de hacerlo es totalmente análoga a cómo se hace en asp.net. No obstante, para aclararlo, voy a proseguir con el ejemplo que he creado.

Obviamente, los archivos de configuración deben tener algo de información, además de tener la misma estructura para todos los entornos.

Los archivos que he utilizado en el ejemplo son los siguientes, para development, preproduction y production, respectivamente.

{
  "Info": {
    "Environment": "DEV",
    "Greettings": "Hello from development environment"
  }
}
{
  "Info": {
    "Environment": "PRE",
    "Greettings": "Hello from preproduction environment"
  }
}
{
  "Info": {
    "Environment": "PRO",
    "Greettings": "Hello from production environment"
  }
}
Anuncios
INFORMA SOBRE ESTE ANUNCIOPRIVACIDAD

Para validar que las configuraciones se leen correctamente, he creado una View en la que muestro 2 labels, una para cada valor del archivo de configuración.

Para asignar valor a esas labels, recibo el IConfiguration de la app en el constructor y accedo a los valores que me interesan.

public partial class MainPage 
{
    public MainPage(IConfiguration configuration)
    {        
        InitializeComponent();

        lbEnvironment.Text = $"Environment: {configuration.GetValue<string>("Info:Environment")}";
        lbGreetings.Text = $"Greetings: {configuration.GetValue<string>("Info:Greettings")}";
    }
}

Con todo lo anterior, ya tendríamos un ejemplo creado en el que utilizar un appsettings por cada entorno, lo que hará más sencillos nuestros desarrollos, pruebas y despliegues a cada uno de esos entornos.

He dejado el código del ejemplo anterior en el siguiente repo: https://github.com/jorgediegocrespo/MauiSettings

mm

Sobre Jorge Diego

Soy un apasionado del desarrollo de software. Me encanta mi trabajo y mantenerme al día haciendo cursos, investigando, realizando proyectos personales, etc. Principalmente trabajo con tecnología .NET. Asimismo, me interesa muchísimo el mundo de la productividad personal. Además del desarrollo tengo otras muchas aficiones: viajar, deporte, gastronomía, fotografía…y sobre todo, pasar tiempo con mi familia.
Esta entrada ha sido publicada en .NET, Cloud. Enlace permanente.
ENCAMINA, piensa en colores