11 czerwca 2008
Konfiguracja aplikacji - własne podejście
Każda aplikacja nie może się obyć bez konfiguracji. W ASP.NET mamy do dyspozycji web.config, który z jednej strony zawiera ustawienia aplikacji dotyczące platformy, framework'a, a z drugiej własne ustawienia aplikacji - appSettings. Czasami zdarza się, że tych ustawień może być bardzo dużo co powoduje zmniejszoną czytelność i pomieszanie z ustawieniami systemowymi. Dlatego też w każdej aplikacji, którą tworzę korzystam z własnego mechanizmu przechowywania ustawień. Rozdzielenie tych ustawień powoduje, że mój plik web.config zawiera podstawowe tagi frameworka, które są niezależne od aplikacji.
Stworzyłem zatem prostą klasę AppConfig, która implementuje znany pattern Singleton. W chwili pierwszego skorzystania z obiektu klasa zostaje zainicjalizowana i zostają załadowane wszystkie ustawienia aplikacji.
private static AppConfig config = null;
public static AppConfig Current
{
get
{
if(config == null)
{
lock(typeof(AppConfig))
{
if(config == null)
{
config = new AppConfig();
}
}
}
return config;
}
}
Ustawienia zapisywane są w prostym pliku XML o stałej nazwie 'application.xml', który zawiera proste elementy.
<config>
<!-- Configuration for production server -->
<application.name>Project name</application.name>
<shared.upload-directory>C:\Project\shared</shared.upload-directory>
</config>
Do załadowania danych użyłem poprostu XMlDocument, który ładuje wszystkie tagi pokolei do kolekcji. Dodatkowo konfigurator szuka pliku o nazwie 'application.machineName.xml', gdzie dla danej maszyny można nadpisać ustawienia z podstawowego pliku konfiguracyjnego. I tak dla przykładu w podstawowym pliku mamy ustawienia takie jakie obowiązują w środowisku produkcyjnym. W plikach rozszerzających mamy konfigruację, na przykład developerską, która jest prywatna dla maszyny danego developera.
Każdy programista w zespole może stworzyć własną konfigurację nadpisując tylko te pozycje, które wymagają zmiany do uruchomienia aplikacji na danej maszynie. Przykładowo połączenie do bazy danych, z którą komunikuje się aplikacja może być zupełenie inne niż na produkcji, czy u innego programisty.
Pobranie danego ustawienia wymaga podania konkretnego klucza oraz typu danych jaki spodziewamy się uzyskać. Mamy do wyboru dwie metody. Pierwsza oczekuje istnienia parametru w konfiguracji. Jeśli podanego parametru nie ma to zostanie wyrzucony wyjątek. Druga metoda pozwala na podanie wartości domyślnej i oznacza to, że parametr jest niewymagany i nie musi istnieć w konfiguracji. Dopisanie takiego parametru przesłoni domyślną wartość podaną w kodzie.
public T GetItem<T>(string key)
{
lock (locker)
{
if (!items.ContainsKey(key))
{
throw new NotImplementedException(String.Format("The key '{0}' is not defined in application config file.", key));
}
return (T)Convert.ChangeType(items[key], typeof(T));
}
}
public T GetItem<T>(string key, T defaultValue)
{
lock (locker)
{
if (items.ContainsKey(key))
{
return (T)Convert.ChangeType(items[key], typeof(T));
}
return defaultValue;
}
}
A poniżej przykład pobrania wartości:
string _name = AppConfig.Current.GetItem<string>("application.name");
Niektórzy mogą zapytać po co takie zmyślne i długie nazwy parametrów. Otóż mam w tym dwa cele. Po pierwsze parametr jest dobrze opisany i nazwa tagu odrazu wiele mówi. Po drugie dzielenie nazwy kropką na segmenty daje mi możliwość udoskonalenia mechanizmu, ale o tym w kolejnym poście. :)
Kod źródłowy całej klasy AppConfig - zapraszam do pobrania i korzystania/eksperymentowania. :)
PS
Na fali ostatnich wydarzeń post ten ukazał się tylko na zine.net.pl i nie jest dostępny na mojej prywatnej stronie. :)
PS2
Kod AppConfig używa kilka dodatkowych elementów i bez nich się nie kompiluje, ale zamieszczam go tutaj raczej w celach ogólno-poglądowych całego rozwiązania.
Powiadamianie o komentarzach
Jeżeli chciałbyś otrzymywać email gdy ta wypowiedź zostanie zaktualizowana, to zarejestruj się tutaj
Subskrybuj komentarze za pomocą
Comment Policy: No HTML allowed. URIs and line breaks are converted automatically. Your e–mail address will not show up on any public page.