Se la soluzione è dietro l’angolo spesso la ignoriamo…
La gestione dei settings di un’applicazione
VisualStudio ci mette a disposizione un’infrastruttura eccelsa per la gestione dei settings, che va mostruosamente oltre il mero file “ini”, non foss’altro perchè, ad esempio:
- è fortemente tipizzata;
- è “a gratis” user o application scoped;
- offre un designer integrato nell’ambiete di sviluppo, con tutto quello che questo comporta, come ad esempio il pieno supporto per il refactoring… che è tutto tranne che poco ;-)
Oggi nell’applicare la mia nuova policy ho riscritto un piccolo componente che uso da qualche “secolo” aggiornandolo a Linq, il componente è un SettingsProvider.
MyDatabaseSettingsProvider
Gli unici 2 metodi degni di nota sono:public sealed class MyDatabaseSettingsProvider : SettingsProvider { private readonly String connectionString; public MyDatabaseSettingsProvider() { this.connectionString = ConfigurationManager.ConnectionStrings[ "SettingsCN" ].ConnectionString; } public override string ApplicationName { get; set; } public override void Initialize( string name, NameValueCollection config ) { if( String.IsNullOrEmpty( name ) ) { name = "DatabaseSettingsProvider"; } base.Initialize( name, config ); } public override SettingsPropertyValueCollection GetPropertyValues( SettingsContext context, SettingsPropertyCollection collection ) { var valueCollection = new SettingsPropertyValueCollection(); using( var dc = new SettingsDataContext( this.connectionString ) ) { foreach( SettingsProperty setting in collection ) { var settingValue = new SettingsPropertyValue( setting ); settingValue.IsDirty = false; var key = settingValue.Name; var dbSetting = dc.Settings.Where( s => s.Name == key ).SingleOrDefault(); if( dbSetting != null ) { settingValue.SerializedValue = dbSetting.SerializedValue; } valueCollection.Add( settingValue ); } } return valueCollection; } public override void SetPropertyValues( SettingsContext context, SettingsPropertyValueCollection collection ) { using( var dc = new SettingsDataContext( this.connectionString ) ) { foreach( SettingsPropertyValue propval in collection ) { if( !propval.UsingDefaultValue && propval.IsDirty ) { var key = propval.Name; var dbSetting = dc.Settings.Where( s => s.Name == key ).SingleOrDefault(); if( dbSetting != null ) { dbSetting.SerializedValue = ( String )propval.SerializedValue; } else { var setting = new Setting(); setting.Name = key; setting.SerializedValue = ( String )propval.SerializedValue; setting.ValueType = propval.Property.PropertyType.ToShortString(); dc.Settings.InsertOnSubmit( setting ); } dc.SubmitChanges(); } } } } }
- GetPropertyValues: questo metodo viene chiamato dall’infrastruttura dei Settings di Visual Studio la prima volta che accedete all’instanza statica, esposta come singleton, dei settings: Properties.Settings.Default… per intenderci;
L’infrastruttura vi passa un context, che è un dictionary in cui ci potete mettere un sacco di belle cose, e una collection che rappresenta l’elenco dei settings di cui ha bisogno che venga caricato il valore; - SetPropertyValues: questo metodo viene invece chiamato quando l’infrastruttura dei settings ha bisogno di salvare i settings, attenzione che viene chiamato solo per i settings che hanno user scope, e vi passa il “solito” context e l’elenco dei settings che devono essere salvati.
Ma come si usa? nulla di più semplice, prendete un qualsiasi file di settings (o quello di default, o uno custom vostro non è importante) e “pigiate” View Code nel designer:
Visual Studio vi aggiunge al progetto una partial class che “estende” la classe dei settings generata dal designer stesso:
L’unica cosa che dovete fare è aggiungere in testa alla classe l’attributo SettingsProvider specificando il tipo del vostro provider, Visual Studio provvederà al resto :-).[SettingsProvider( typeof( MyDatabaseSettingsProvider ) )] internal sealed partial class Settings { public Settings() { this.Context.Add( "MyKey", "MyValue" ); } }
Che vataggi abbiamo?
- usiamo l’infrastruttura dei settings di Visual Studio senza reinventare la ruota;
- usiamo il designer di Visual Studio, ndr: l’ambiente di sviluppo continuerà a creare il file app.config e continuerà a metterci i valori specificati nel designer, ma il file serve solo a Visual Studio per funzionare non vi serve farne il deploy;
- Abbiamo investito veramente pochissimo tempo (circa 20 minuti) in una soluzione decisamente riutilizzabile;
.m