Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Xamarin.Forms : avoir des configs différentes en debug/release (automatiquement)

Dans la plupart des projets on a besoin de changer certaines valeurs en debug et en release. Par exemple l’URL d’un serveur, une clé de licence, l’affichage d’un menu de debug spécial, etc. Comment automatiser tout cela ?

Le principe du fichier Settings

Certains types de projets .NET proposent un Settings.Json ou équivalent pour y ranger des valeurs différenciée entre debug et release mais ce n’est pas le cas des Xamarin.Forms.

L’idée consiste ainsi à simuler de la façon la plus simple un tel mécanisme à l’aide d’un fichier JSON, plus exactement deux, l’un pour le debug et l’autre pour la release. De cette façon plus aucune question à se poser, et surtout plus d’embrouille de type livraison d’un fichier pointant sur un serveur réel pour du debug ou l’inverse … Bourdes qui peuvent faire des dégâts.

Etape 1 : définir le fichier JSON

Sans donner dans les grandes complications ce qu’on cherche avant tout ici c’est un fichier de type dictionnaire clé/valeur. Il est donc très facile de créer un fichier JSON de ce type (les clés et les valeurs sont là pour la démo, mettez ce dont vous avez besoin bien entendu !) :

settings.json:
{
	"ServerUrl": "https://myserver.com/api/",
	"apiKey": "123456"
}

On imagine ici qu’il s’agit du fichier de configuration “release” utilisant l’adresse d’un serveur (dit de production) ainsi qu’une clé d’API qui permet d’accéder à des services externes (Amazon, Google ou n’importe quoi qui nécessite une clé API, mais rappelez-vous ces clés/valeurs ne sont que des exemples pour la démo).

Pour le développement, en mode debug donc, il est souvent préférable d’utiliser un serveur de test, on peut aussi être amené à utiliser une clé d’API réservée aux tests (toujours dans cet exemple hypothétique). Ainsi notre fichier de settings va ressembler à cela pour le debug :

local.settings.json
{
	"ServerUrl": "https://localhost:6003/api/",
	"apiKey": "654321"
}

On remarquera le nom du fichier qui commence désormais par “local” mais ce n’est une fois encore qu’un exemple vous pouvez appeler ce fichier debug.settings.json ou toto.json si cela vous chante…

Etape 2 : ajouter le fichier au projet

Nous disposons de deux fichiers JSON, l’un pour le déploiement en mode release l’autre pour le mode debug. C’est chouette. Mais en fait il manque tout de même un petit bout de quelque chose pour accrocher les wagons et faire en sorte que ce soit bien l’un ou l’autre qui soit utilisé selon le cas.

C’est une manipulation assez simple à réaliser en jouant de façon très légère avec MSBUILD directement dans le fichier du projet.

Ce qu’on cherche c’est à inclure soit l’un soit l’autre fichier selon que le debug ou release est activé. Mais aussi, et c’est très important, que dans les deux cas le fichier s’appelle toujours settings.json car l’application ne doit pas à avoir faire la différence entre les deux modes, elle utilise toujours settings.json. C’est à nous de feinter et de faire apparaitre la ressource sous ce nom dans les deux cas.

Ce n’est pas si difficile et voici un exemple de fichier projet modifié :

Le fichier .CSPROJ :
<ItemGroup>
	<EmbeddedResource
		Include="settings.json"
		Condition="'$(Configuration)' != 'Debug' or !Exists('local.settings.json')" />
	<EmbeddedResource
		Include="local.settings.json"
		Link="settings.json"
		Condition="'$(Configuration)' == 'Debug' and Exists('local.settings.json')" />
</ItemGroup>


Les deux fichiers sont intégrés en mode “Ressource intégrée” (EmbeddedResource).

Pour chaque fichier intégré dans le projet des conditions ont été ajoutées. Par exemple le fichier settings.json sera intégré au projet si et seulement si la configuration de compilation n’est pas Debug ou si aucun local.settings.json n’existe déjà. Ce dernier sera lui intégré seulement si on est en Debug et que le fichier existe déjà.

Ce n’est une fois encore qu’un exemple et vous pouvez créer les conditions que vous voulez, en rendant le tout plus simple (tester uniquement Debug) ou plus sophistiqué (allez savoir ça doit bien se justifier dans certains cas !).

L’autre point important à noter est que le fichier de debug possède une instruction de plus, “Link=settings.json” cela signifie que le fichier sera renommé pour s’appeler exactement comme celui de release. C’est ce qui était expliqué plus haut, release ou debug notre App ne doit pas avoir à faire la différence, tout est automatique ce qui évite du code, des bugs, et bien des ennuis !

Etape 3 : accéder aux réglages

C’est bien d’avoir un fichier en ressources mais encore faut-il le lire et en sortir un dictionnaire clé/valeur utilisable par l’App…

Là il ne s’agit que de code très classique mais je vous le montre pour que l’article se suffise à lui-même sans vous envoyer lire d’autres papiers :

// Obtenir l’assemblage en cours d’exécution
var assembly = Assembly.GetExecutingAssembly();

// On cherche dans les ressources le fichier se terminant
// par settings.json. Bien entendu si vous fixez le nom en dur
// une fois pour toute, utilisez le nom directement
var resName = assembly.GetManifestResourceNames()
	?.FirstOrDefault(r => r.EndsWith("settings.json", StringComparison.OrdinalIgnoreCase));

// Chargement en mémoire de la ressource
using var file = assembly.GetManifestResourceStream(resName);

// lire tout le fichier dans un stream
using var sr = new StreamReader(file);

// Lire le fichier
var json = sr.ReadToEnd();

// Parser le fichier comme étant du JSON
var j = JObject.Parse(json);
// extraire les valeurs et les ranger quelque part
// par exemple en variable statique dans App.Xaml.cs ou ailleurs
// à vous de voir… var ServerUrl = j.Value<string>("ServerUrl"); var apiKey = j.Value<string>("apiKey");

Comme indiqué il s’agit ici d’un code classique pour lire une ressource et l’interpréter comme un fichier JSON puis en extraire les valeurs pertinentes.

Vous pouvez utiliser d’autres méthodes plus simples, des packages spécialisés, etc, ce n’est pas la partie la plus intéressante du code exemple de ce papier.

Conclusion

Et bien c’est tout… votre App va lire des paramètres qui selon que vous serez en debug ou en release seront différents. Plus d’erreur possible. La mise à jour des fichiers settings se fait avec le bloc-note au plus simple (ou dans VS), pas de bricolage savant, rien, du simple, du direct et de l’automatique !

Comme vous l’avez compris rien n’interdit de jouer plus subtile avec MSBUILD pour créer des choses plus sophistiquées. Personnellement je ne suis pas un spécialiste de MSBUILD et de ses arcanes, alors ce minimum vital montré ici me satisfait parfaitement. Je n’aime pas les trucs alambiqués, c’est la porte ouverte aux bugs et à des incompréhensions dans des équipes de dev où le niveau est hétérogène. Si je ne fais pas non plus la promotion d’un code “’bourrin” je pense que la vérité est entre les deux pour assurer lisibilité du code et maintenabilité ce qui d’un point de vue industriel sont des critères bien plus lourds dans la balance que l’exotisme ou les démonstrations de savoir-faire ultra-pointus.

Bref à vous de jouer, et

Stay Tuned !

blog comments powered by Disqus