Guarda! Senza mani! - Quinta parte
a cura di Sabrina Cosolo e Diego Cattaruzza (requisiti: conoscenza intermedia di Sql Server e di .Net)Ancora un po' di pazienza
Per sviluppare la classe di gestione delle impostazioni nell'applicazione, UsingSqlServerConfig, aggiungiamo alla classe IoHelper altri quattro metodi. Infatti, per gestire i file di configurazione, ci serve un metodo che ci restituisca la cartella di installazione dell'applicazione, un metodo che ci restituisca il nome del file di setting dell'applicazione ed un metodo che ci restituisca il nome del file di setting dell'utente. Per cucinare tutto questo, bisogna utilizzare un po' di Environment, un po' di Reflection, condire con qualche metodo delle classi di IO e l'helper è pronto.using System.IO;Imports System.IOPrima aggiungiamo una direttiva utile.
public static string GetAppDir() { return AppDomain.CurrentDomain.SetupInformation.ApplicationBase; }public static string GetAppDir(string pPath) { if (pPath == null) pPath = String.Empty; return Path.Combine(GetAppDir(), pPath); } Public Shared Function GetAppDir() As String Return My.Application.Info.DirectoryPath End Function Public Shared Function GetAppDir(ByVal nomeFile As String) As String If nomeFile Is Nothing Then nomeFile = String.Empty Return Path.Combine(GetAppDir(), nomeFile) End FunctionEcco i primi due metodi aggiunti a IoHelper, che ci restituiscono il nome della cartella di installazione dell'applicazione e il nome di un file specifico mappato sulla cartella dell'applicazione. Vi chiederete perché scomodare una cosa come l'AppDomain per generare la cartella corrente. Vi rispondiamo in anticipo: perché, se l'applicazione, in qualsivoglia modo, contiene degli OpenFileDialog o dei SaveFileDialog, o comunque qualsiasi funzione che possa cambiare la cartella corrente dell'applicazione, il metodo che ci fornisce il path corrente non ci dà quel che ci serve.
Per i prossimi due metodi, abbiamo bisogno di crearci una eccezione personalizzata, ed anche una risorsa (un messaggio 'tipico'). Quindi, tasto desto su TAndT.Base, aggiungiamo una nuova classe di nome InvalidParameterException (simile alle altre: ci serve un nome esplicativo):
namespace TAndT.Base { public class InvalidParameterException : System.ApplicationException { public InvalidParameterException(string pMessage) : base(pMessage) { } } }Public Class InvalidParameterException Inherits System.ApplicationException Public Sub New(ByVal message As String) MyBase.New(message) End Sub End ClasSe in Solution Explorer non vediamo tutti i file, clicchiamo sull'icona apposita e poi apriamo il Resources.resx - se non c'è aggiungiamolo. clic destro su TAndT.Base.Properties per C# - della TAndT.Base, aggiungendovi una risorsa:
warIOHNoProductName Il nome prodotto indicato è vuoto public static string CreateAppConfigFileName(string pApplication) { if (pApplication == null || pApplication.Trim().Length == 0) { throw new InvalidParameterException(Properties.Resources.warIOHNoProductName); } string filename = string.Format("{0}App.ttcfg", pApplication); return (GetAppDir(filename)); }Public Shared Function CreateAppConfigFileName(ByVal application As String) As String If String.IsNullOrEmpty(application) Then Throw New InvalidParameterException(My.Resources.warIOHNoProductName) End If Dim fileName As String = String.Format("{0}App.ttcfg", application) Return GetAppDir(fileName) End FunctionIl terzo metodo ci crea il nome del file di configurazione, passato il nome dell'applicazione, lanciando l'eccezione col messaggio appena creati nel caso il parametro passato sia vuoto.
Per il quarto metodo abbiamo bisogno di essere sicuri dell'esistenza di una cartella, quindi ne creiamo un quinto:
public static void CheckCreateDir(string pDir) { try { if (!System.IO.Directory.Exists(pDir)) { System.IO.Directory.CreateDirectory(pDir); } } catch (Exception ex) { throw new ApplicationException(" " + mClassName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, ex); } }Public Shared Sub CheckCreateDir(ByVal directoryPath As String) Try If Not Directory.Exists(directoryPath) Then Directory.CreateDirectory(directoryPath) End If Catch ex As Exception Throw New ApplicationException(" " + mClassName + "." _ + System.Reflection.MethodBase.GetCurrentMethod().Name, ex) End Try End SubEsso controlla se una cartella esiste e la crea se non esiste.
public static string CreateUsrConfigFileName(string pApplication) { if (pApplication == null || pApplication.Trim().Length == 0) { throw new InvalidParameterException(Properties.Resources.warIOHNoProductName); } string baseDir = Path.Combine(Environment.GetEnvironmentVariable("APPDATA"), "TAndT"); CheckCreateDir(baseDir); baseDir = Path.Combine(baseDir, pApplication); CheckCreateDir(baseDir); string filename = string.Format("{0}Usr.ttcfg", pApplication); return (Path.Combine(baseDir, filename)); }Public Shared Function CreateUsrConfigFileName(ByVal application As String) As String If String.IsNullOrEmpty(application) Then Throw New InvalidParameterException(My.Resources.warIOHNoProductName) End If Dim baseDir As String = Path.Combine(Environment.GetEnvironmentVariable("APPDATA"), "TAndT") CheckCreateDir(baseDir) baseDir = Path.Combine(baseDir, application) CheckCreateDir(baseDir) Dim fileName As String = String.Format("{0}Usr.ttcfg", application) Return Path.Combine(baseDir, fileName) End FunctioIl quarto metodo, forse un po' più interessante, genera il nome per il file delle impostazioni per l'utente. Facciamo notare l'uso di GetEnvironmentVariable, che ci permette di richiedere al sistema qual è la cartella Application Data (Dati Applicazioni) dell'utente corrente. Questa cartella è indicata nelle best practices come la cartella sotto cui tutte le applicazioni dovrebbero salvare i dati di configurazione utente. Per essere più pignoli, ci deve essere una sottocartella con il nome dell'azienda, con all'interno una con il nome dell'applicazione, nella quale ultima memorizzare il file. Ecco perché ricorriamo più volte al metodo CheckCreateDir.
Se siete curiosi e volete vedere quante e quali sono le variabili di ambiente della vostra macchina, aprite una finestra console (Start, run, cmd, su Windows XP), scrivete SET e premete <invio>: la lista che compare può essere interrogata con il metodo GetEnvironmentVariable, anche se alcune variabili quali Username e DomainName sono già mappate nella classe Environment.
Nel nostro caso, il risultato della chiamata al metodo che richiede il nome del file dei setting di applicazione è qualcosa come:
C:\Documents and Settings\Username\Dati applicazioni\TAndT\UsingSqlServer2005\UsingSqlServer2005Usr.ttcfg.Andiamo a fare un test sulla nostra FrmMain e aggiungiamo al menu Setting Manager Tests un menu dal titolo Test Set App User Config Path, per il quale Visual Studio ci genererà un nuovo ToolStripMenuItem al cui evento click associeremo il seguente codice:
private void testSetAppUserConfigPathToolStripMenuItem_Click(object sender, EventArgs e) { try { StringBuilder sb = new StringBuilder(); sb.AppendLine("Test Valori files di configurazione "); sb.AppendLine(IoHelper.CreateUsrConfigFileName("UsingSqlServer2005")); sb.AppendLine(IoHelper.CreateAppConfigFileName("UsingSqlServer2005")); Warnings.Info(sb.ToString()); } catch (Exception ex) { Warnings.Errore(mClassName, System.Reflection.MethodBase.GetCurrentMethod(), ex); } }Private Sub TestSetAppUserConfigPathToolStripMenuItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles TestSetAppUserConfigPathToolStripMenuItem.Click Try Dim sb As New StringBuilder sb.AppendLine("Test Valori files di configurazione") sb.AppendLine(IoHelper.CreateUsrConfigFileName("UsingSqlServer2005")) sb.AppendLine(IoHelper.CreateAppConfigFileName("UsingSqlServer2005")) Warnings.Info(sb.ToString) Catch ex As Exception Warnings.Errore(mClassName, System.Reflection.MethodBase.GetCurrentMethod(), ex) End Try End SubIl risultato di questo fantastico test sulla macchina di Sabrina è il seguente:
Come vedete, abbiamo usato una estensione non standard (ttcfg), per fare in modo che questi file siano proprio nostri, anche se sono meri file XML.
Potete anche provare a togliere UsingSqlServer2005 per vedere l'errore.La classe UsingSqlServerConfig
Questa classe sarà una classe statica. "Ancora? - direte voi - ma com'è possibile che facciamo solo classi statiche?"
Effettivamente, nell'ossatura di una applicazione ne servono varie, ma non dubitate che avrete molti e numerosi oggetti con cui lavorare molto presto.Questa classe conterrà innanzitutto un TAndTSettingsManager per la gestione dei file, poi due variabili readonly per i nomi dei suddetti file, una costante con il nome di ciascuno dei setting che per ora utilizzeremo, un metodo per il caricamento dei setting con la generazione automatica di quelli che non fossero presenti nella lista su disco, una serie di proprietà che mapperanno i setting all'esterno della classe, in maniera che siano reperibili in modo per così dire "tipizzato", un metodo per il salvataggio dei setting... e per ora ci fermiamo qui (se del caso, aggiungeremo altro).
Posizioniamoci su UsingSqlServer, facciamo Add>Class> e generiamo una classe che chiamiamo UsingSqlServerConfig.
using System; using System.Collections.Generic; using System.Text; using TAndT.Base; using TAndT.Base.Collections; namespace TAndT.UsingSqlServer { public static class UsingSqlServerConfig { private static readonly string mClassName = System.Reflection.MethodBase.GetCurrentMethod().ReflectedType.Name; } }Imports System Imports System.Collections.Generic Imports System.Text Imports TAndT.Base Imports TAndT.Base.Collections Public Class UsingSqlServerConfig Private Shared ReadOnly mClassName As String = _ System.Reflection.MethodBase.GetCurrentMethod.ReflectedType.Name End ClassAggiungiamo le direttive giuste e la solita mClassName. Curiamoci di indicare (o verificare) il namespace: chi scrive in VB controlli la correttezza del proprio Namespace e tenga presente il fatto che la classe è statica, che cioè tutti i suoi membri dovranno essere shared.
Aggiungiamo una regione:#region Constants public const string APP_NAME = "UsingSQLServer"; public const string STT_APPSqlDatabase = "SqlDatabase"; public const string STT_APPSqlServer = "SqlServer"; private const string DEFAULT_MyDatabase = "myDatabase"; private const string DEFAULT_MyPassword = "myPassword"; private const string DEFAULT_MyServer = "myServer"; private const string DEFAULT_MyUser = "myUser"; private const string DEFAULT_True = "true"; private const string SYSDB_Master = "Master"; private const string SYSDB_Msdb = "Msdb"; public const string STT_USRPassword = "Password"; public const string STT_USRTrusted = "Trusted"; public const string STT_USRUserId = "UserID"; #endregion#Region "Costanti" Public Const APP_NAME As String = "UsingSQLServer" Public Const STT_APPSqlDatabase As String = "SqlDatabase" Public Const STT_APPSqlServer As String = "SqlServer" Private Const DEFAULT_MyDatabase As String = "myDatabase" Private Const DEFAULT_MyPassword As String = "myPassword" Private Const DEFAULT_MyServer As String = "myServer" Private Const DEFAULT_MyUser As String = "myUser" Private Const DEFAULT_True As String = "true" Private Const SYSDB_Master As String = "Master" Private Const SYSDB_Msdb As String = "Msdb" Public Const STT_USRPassword As String = "Password" Public Const STT_USRTrusted As String = "Trusted" Public Const STT_USRUserId As String = "UserID" #End RegioQueste costanti rappresentano:
- Il nome dell'applicazione (anche se, volendo, questo si può ricavare dal nome dell'assembly o dal ProductName o dal Title, che sono attributi dell'assembly, abbiamo deciso. in questo caso, per semplicità e comodità, di creare una costante).
- I nomi dei setting di applicazione (prefisso APP).
- I valori dei default applicati ai vari setting alla loro creazione (prefisso DEFAULT).
- I nomi dei database di sistema con cui dovremo lavorare in SQL Server per la composizione delle stringhe di connessione. (prefisso SYSDB)
- I nomi dei setting utente (prefisso USR).
private static readonly string mAppFileName = IoHelper.CreateAppConfigFileName(APP_NAME); private static readonly string mUserFileName = IoHelper.CreateUsrConfigFileName(APP_NAME); private static TAndTSettings mAppSettings; private static TAndTSettings mUserSettings;Private Shared ReadOnly mAppFileName As String = IoHelper.CreateAppConfigFileName(APP_NAME) Private Shared ReadOnly mUserFileName As String = IoHelper.CreateUsrConfigFileName(APP_NAME) Private Shared mAppSettings As TAndTSettings Private Shared mUserSettings As TAndTSettingsLe variabili a livello di classe sono quattro, i nomi dei due file dati e le collezioni dei setting, i nomi dei file li componiamo immediatamente in quanto non modificabili dall'utente, le collezioni sono campi relativi a proprietà (che seguono in ordine sparso, con qualche preparazione laddove occorre).
public static TAndTSettings AppSettings { get { return mAppSettings; } set { mAppSettings = value; } } public static TAndTSettings UserSettings { get { return mUserSettings; } set { mUserSettings = value; } } public static bool Trusted { get { bool ret = false; if (!bool.TryParse(UserSettings[STT_USRTrusted].Value, out ret)) { ret = false; } return ret; } set { bool ret = false; if (bool.TryParse(value.ToString(), out ret)) { UserSettings[STT_USRTrusted].Value = ret.ToString(); } else { UserSettings[STT_USRTrusted].Value = false.ToString(); } } } public static string SqlServer { get { return AppSettings[STT_APPSqlServer].Value; } set { AppSettings[STT_APPSqlServer].Value = value; } } public static string SqlDatabase { get { return AppSettings[STT_APPSqlDatabase].Value; } set { AppSettings[STT_APPSqlDatabase].Value = value; } } public static string UserID { get { return UserSettings[STT_USRUserId].Value; } set { UserSettings[STT_USRUserId].Value = value; } } public static string Password { get { return UserSettings[STT_USRPassword].Value; } set { UserSettings[STT_USRPassword].Value = value; } }Public Shared Property AppSettings() As TAndTSettings Get Return mAppSettings End Get Set(ByVal value As TAndTSettings) mAppSettings = value End Set End Property Public Shared Property UserSettings() As TAndTSettings Get Return mUserSettings End Get Set(ByVal value As TAndTSettings) mUserSettings = value End Set End Property Public Shared Property Trusted() As Boolean Get Dim ret As Boolean = False If Not Boolean.TryParse(UserSettings(STT_USRTrusted).Value, ret) Then ret = False End If Return ret End Get Set(ByVal value As Boolean) Dim ret As Boolean = False If Boolean.TryParse(value.ToString, ret) Then UserSettings(STT_USRTrusted).Value = ret.ToString Else UserSettings(STT_USRTrusted).Value = False.ToString End If End Set End Property Public Shared Property SqlServer() As String Get Return AppSettings(STT_APPSqlServer).Value End Get Set(ByVal value As String) AppSettings(STT_APPSqlServer).Value = value End Set End Property Public Shared Property SqlDatabase() As String Get Return AppSettings(STT_APPSqlDatabase).Value End Get Set(ByVal value As String) AppSettings(STT_APPSqlDatabase).Value = value End Set End Property Public Shared Property UserID() As String Get Return UserSettings(STT_USRUserId).Value End Get Set(ByVal value As String) UserSettings(STT_USRUserId).Value = value End Set End Property Public Shared Property Password() As String Get Return UserSettings(STT_USRPassword).Value End Get Set(ByVal value As String) UserSettings(STT_USRPassword).Value = value End Set End PropertyOltre alle proprietà che mappano le due collezioni dei setting, per renderle accessibili per qualsiasi uso (sicuramente ne troveremo qualcuno), ci sono delle proprietà che mappano gli elementi delle collezioni, il che ci permette di poter tipizzare i setting anche se sul file dati vengono memorizzati come stringa. Un esempio è il setting Trusted, che stabilisce se utilizzare una connessione trusted oppure una connessione SQL, che viene restituito come booleano dal get e impostato come stringa dal set.
Per alcune proprietà bisogna implementare un metodo per validare la classe:
public static bool IsValid() { bool ret = false; try { if (Trusted) { ret = (SqlServer != null && SqlServer.Trim().Length > 0 && SqlDatabase != null && SqlDatabase.Trim().Length > 0); } else { ret = (SqlServer != null && SqlServer.Trim().Length > 0 && SqlDatabase != null && SqlDatabase.Trim().Length > 0 && UserID != null && UserID.Trim().Length > 0); } } catch (Exception) { ret = false; } return (ret); }Public Shared Function IsValid() As Boolean Dim ret As Boolean = False Try If Trusted Then ret = Not (String.IsNullOrEmpty(SqlServer) OrElse String.IsNullOrEmpty(SqlDatabase)) Else ret = Not (String.IsNullOrEmpty(SqlServer) OrElse String.IsNullOrEmpty(SqlDatabase) _ OrElse String.IsNullOrEmpty(UserID)) End If Catch ex As Exception ret = False End Try Return ret End FunctionIl metodo di validazione della classe ci permette di stabilire se i setting della connection string sono corretti o meno, anche se in modo superficiale. Infatti, da qui non viene controllato se il server o il database esistono e sono validi, ma viene fatto un mero controllo di correttezza formale.
Ovviamente, il controllo di validazione della connessione dovrà essere affidato ad una funzione specifica che scriveremo in seguito.E' necessario anche aggiungere alcune risorse, quindi apriamo il file Resources.resx di UsingSqlServer - per C#, bisogna aggiungerlo alle Properties:
SqlConnectionSql Data Source={0}; Initial Catalog={1}; Persist Security Info=True; User ID={2};Password={3} SqlConnectionTrusted Data Source={0}; Initial Catalog={1}; Integrated Security=True Queste sono le stringhe di formato per le nostre connectionstring. Adesso siamo pronti per implementare altre proprietà:
public static string CnString { get { string retCnStr = string.Empty; if (IsValid()) { if (Trusted) { retCnStr = string.Format(Properties.Resources.SqlConnectionTrusted, SqlServer, SqlDatabase); } else { retCnStr = string.Format(Properties.Resources.SqlConnectionSql, SqlServer, SqlDatabase, UserID, Password); } } return (retCnStr); } } public static string CnStringMaster { get { string retCnStr = string.Empty; if (Trusted) { if (SqlServer != null && SqlServer.Trim().Length > 0) { retCnStr = string.Format(Properties.Resources.SqlConnectionTrusted, SqlServer, SYSDB_Master); } } else { if (SqlServer != null && SqlServer.Trim().Length > 0 && UserID != null && UserID.Trim().Length > 0 && Password != null) { retCnStr = string.Format(Properties.Resources.SqlConnectionSql, SqlServer, SYSDB_Master, UserID, Password); } } return (retCnStr); } } public static string CnStringMsdb { get { string retCnStr = string.Empty; if (Trusted) { if (SqlServer != null && SqlServer.Trim().Length > 0) { retCnStr = string.Format(Properties.Resources.SqlConnectionTrusted, SqlServer, SYSDB_Msdb); } } else { if (SqlServer != null && SqlServer.Trim().Length > 0 && UserID != null && UserID.Trim().Length > 0 && Password != null) { retCnStr = string.Format(Properties.Resources.SqlConnectionSql, SqlServer, SYSDB_Msdb, UserID, Password); } } return (retCnStr); } }Public Shared ReadOnly Property CnString() As String Get Dim retCnStr As String = String.Empty If IsValid() Then If Trusted Then retCnStr = String.Format(My.Resources.SqlConnectionTrusted, SqlServer, SqlDatabase) Else retCnStr = String.Format(My.Resources.SqlConnectionSql, _ SqlServer, SqlDatabase, UserID, Password) End If End If Return retCnStr End Get End Property Public Shared ReadOnly Property CnStringMaster() As String Get Dim retCnStr As String = String.Empty If Trusted() Then If Not String.IsNullOrEmpty(SqlServer) Then retCnStr = String.Format(My.Resources.SqlConnectionTrusted, SqlServer, SYSDB_Master) End If Else If Not String.IsNullOrEmpty(SqlServer) AndAlso Not String.IsNullOrEmpty(UserID) _ AndAlso Not Password Is Nothing Then retCnStr = String.Format(My.Resources.SqlConnectionSql, _ SqlServer, SYSDB_Master, UserID, Password) End If End If Return retCnStr End Get End Property Public Shared ReadOnly Property CnStringMsdb() As String Get Dim retCnStr As String = String.Empty If Trusted Then If Not String.IsNullOrEmpty(SqlServer) Then retCnStr = String.Format(My.Resources.SqlConnectionTrusted, SqlServer, SYSDB_Msdb) End If Else If Not String.IsNullOrEmpty(SqlServer) AndAlso Not String.IsNullOrEmpty(UserID) _ AndAlso Not Password Is Nothing Then retCnStr = String.Format(My.Resources.SqlConnectionSql, _ SqlServer, SYSDB_Msdb, UserID, Password) End If End If Return retCnStr End Get End PropertyDa notare inoltre le property readonly per le connection string: la connection string primaria, che si connette al database applicativo, fa una validazione utilizzando il metodo IsValid e restituisce una connection string valida oppure una stringa vuota. Lo stesso fanno le due connection string ai database di sistema di SQL Server che introduciamo, le cui funzioni saranno spiegate al momento opportuno.
Le connessioni di sistema fanno una validazione locale, in quanto non possono utilizzare IsValid, dato che il database è diverso da quello standard.
In questo modo, ci sarà facile verificare immediatamente da programma la correttezza della connessione al database e richiedere di aggiornarne i parametri, eventualmente.public static void SaveSettings() { try { TAndTSettings.SaveSettings(mAppFileName, true, AppSettings); TAndTSettings.SaveSettings(mUserFileName, true, UserSettings); } catch (Exception ex) { throw new ApplicationException(" " + mClassName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, ex); } }Public Shared Sub SaveSettings() Try TAndTSettings.SaveSettings(mAppFileName, True, AppSettings) TAndTSettings.SaveSettings(mUserFileName, True, UserSettings) Catch ex As Exception Throw New ApplicationException(" " + mClassName + "." _ + System.Reflection.MethodBase.GetCurrentMethod().Name, ex) End Try End SubIl metodo di salvataggio dei setting è semplice, visto che aggiorna solo i due file su disco.
public static void LoadSettings() { try { bool hasToBeSaved = false; TAndTSettings.LoadSettings(mAppFileName, ref mAppSettings); if (!AppSettings.ExistSetting(STT_APPSqlServer)) { AppSettings.Add(STT_APPSqlServer, DEFAULT_MyServer); hasToBeSaved = true; } if (!AppSettings.ExistSetting(STT_APPSqlDatabase)) { AppSettings.Add(STT_APPSqlDatabase, DEFAULT_MyDatabase); hasToBeSaved = true; } TAndTSettings.LoadSettings(mUserFileName, ref mUserSettings); if (!UserSettings.ExistSetting(STT_USRTrusted)) { UserSettings.Add(STT_USRTrusted, DEFAULT_True); hasToBeSaved = true; } if (!UserSettings.ExistSetting(STT_USRUserId)) { UserSettings.Add(STT_USRUserId, DEFAULT_MyUser); hasToBeSaved = true; } if (!UserSettings.ExistSetting(STT_USRPassword)) { UserSettings.Add(STT_USRPassword, DEFAULT_MyPassword); hasToBeSaved = true; } if (hasToBeSaved) { SaveSettings(); } } catch (Exception ex) { throw new ApplicationException(" " + mClassName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, ex); } }Public Shared Sub LoadSetting() Try Dim hasToBeSaved As Boolean = False TAndTSettings.LoadSettings(mAppFileName, mAppSettings) If Not AppSettings.ExistSetting(STT_APPSqlServer) Then AppSettings.Add(STT_APPSqlServer, DEFAULT_MyServer) hasToBeSaved = True End If If Not AppSettings.ExistSetting(STT_APPSqlDatabase) Then AppSettings.Add(STT_APPSqlDatabase, DEFAULT_MyDatabase) hasToBeSaved = True End If TAndTSettings.LoadSettings(mUserFileName, mUserSettings) If Not UserSettings.ExistSetting(STT_USRTrusted) Then UserSettings.Add(STT_USRTrusted, DEFAULT_True) hasToBeSaved = True End If If Not UserSettings.ExistSetting(STT_USRUserId) Then UserSettings.Add(STT_USRUserId, DEFAULT_MyUser) hasToBeSaved = True End If If Not UserSettings.ExistSetting(STT_USRPassword) Then UserSettings.Add(STT_USRPassword, DEFAULT_MyPassword) hasToBeSaved = True End If If hasToBeSaved Then SaveSettings() End If Catch ex As Exception Throw New ApplicationException(" " + mClassName + "." _ + System.Reflection.MethodBase.GetCurrentMethod().Name, ex) End Try End SubIl metodo di caricamento dei setting richiama le funzioni della collection, poi verifica l'esistenza di tutti i setting generandoli se non esistono. In questo modo, abbiamo la certezza che non vi saranno eccezioni per l'errata manipolazione di un file fatta magari da Notepad.
static UsingSqlServerConfig() { LoadSettings(); }Shared Sub New() LoadSetting() End SubIl costruttore (sì, un costruttore statico) viene eseguito automaticamente quando la classe statica è referenziata la prima volta e si occupa di creare le collezioni e caricarle con i dati dei files XML oppure generando i valori di default (chiamando il metodo appena creato).
Arrivederci alla prossima puntata
Per questa puntata basta così, non c'è il test perché questa classe verrà testata per benino nella form che svilupperemo per gestire l'aggiornamento del contenuto dei file di setting, la prima vera form del progetto che servirà a qualche cosa.
Come al solito, il codice fin qui prodotto è scaricabile dall'Area Download.
Potete scrivere Feedback (commenti, critiche, suggerimenti, correzioni) sul blog di Sabrina.