środa, 14 maja 2014

Korzystanie z kilku plików konfiguracyjnych (*.config)

Jak powszechnie wiadomo, w jednej solucji możemy mieć wiele projektów. Każdy z tych projektów może posiadać własny plik konfiguracyjny. Problem może się pojawić w sytuacji, gdy w jednej solucji chcemy korzystać z wielu plików konfiguracyjnych. Przyjrzyjmy się pewnemu realnemu scenariuszowi.

Mamy nasza przykładową aplikację konsolową, która poprawnie działa. Zaszła jednak potrzeba wykorzystania web serwisu (WCF). Zgodnie z dobrymi praktykami, do obsługi WCF tworzymy nowy, osobny projekt jako bibliotekę DLL ('class library'). Aplikacja konsolowa, posiadała już swój plik konfiguracyjny (App.config), więc próba odwołania się konfiguracji naszej biblioteki za pomocą obiektu "ConfigurationManager" spowodowała przeglądanie pliku konfiguracyjnego aplikacji. Ponieważ chcemy oddzielić konfigurację biblioteki od konfiguracji aplikacji potrzebujemy mieć oba pliki rozdzielone oraz możliwość czytania z obu plików.

Jak to należy zrobić?
Rozwiązanie można podzielić na dwa etapy. Konfiguracyjny oraz programistyczny:

W projekcie:
a) zmieniamy nazwę pliku konfiguracyjnego biblioteki, aby oba pliki konfiguracyjne miały różne nazwy
b) we właściwościach pliku konfiguracyjnego biblioteki ustawiamy właściwość "Copy to output Directory" na "Copy always"
c) w projekcie z aplikacją ustawiamy referencję na projekt z biblioteką

W kodzie biblioteki, będziemy się odwoływać do nowego pliku konfiguracyjnego w "niestandardowy" sposób. Pisząc "niestandardowy" mam na myśli w sposób inny niż za pomocą obiektu "ConfigurationManager".

W kodzie, wykorzystujemy obiekt Configuration (System.ServiceModel.Configuration) poprzez wykorzystanie jego właściwości. Przykładowa klasa, za pomocą której będziemy korzystali z nowego pliku konfiguracyjnego wygląda tak:

    public class ConfigurationManagerWrapper
    {
        private Configuration cfg;
        public ConfigurationManagerWrapper()
        {
            var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var fileMap = new ExeConfigurationFileMap
            {
                ExeConfigFilename = string.Concat(path, "\\mail.config")
            };
            cfg = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
        }
        public string GetSetting(string key)
        {
            AppSettingsSection section = (cfg.GetSection("appSettings") as AppSettingsSection);
            var value = section.Settings[key].Value;
            return value;
        }
        public ChannelEndpointElement GetClient(string key)
        {
            var serviceModel = ServiceModelSectionGroup.GetSectionGroup(cfg);
            var endpoints = serviceModel.Client.Endpoints;
            if (endpoints.Count > 0)
                return endpoints[0];
            return null;
        }
        public T GetSection<T>(string sectionName)
        {
            return (T)ConfigurationManager.GetSection(sectionName);
        }
    }
Bardziej zaawansowany przykład wykorzystania takiego pliku .config można zobaczyć w przeznaczonym do tego projekcie na github mojego autorstwa stworzonym w celu demonstracji kodu.

Pomocne linki:
stackoverflow.com - how-do-i-retrieve-appsettings-from-the-assembly-config-file
weblogs.asp.net - cibrax - getting-wcf-bindings-and-behaviors-from-any-config-source.aspx

Brak komentarzy:

Prześlij komentarz