2012-07-30 11 views
5

Czy istnieje sposób na załadowanie ustawień z innego pliku niż domyślny plik App.config w środowisku wykonawczym? Chciałbym to zrobić po załadowaniu domyślnego pliku konfiguracyjnego.Ładowanie właściwości.Zestawienia z innego pliku w czasie wykonywania

Używam GUI Settings.Settings w Visual Studio do utworzenia mojego pliku App.config dla mnie. Plik konfiguracyjny kończy się wyglądać jak ten:

<?xml version="1.0" encoding="utf-8" ?> 
    <configuration> 
     <configSections> 
      <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > 
     <section name="SnipetTester.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 
    </sectionGroup> 
    </configSections> 
     <applicationSettings> 
     <SnipetTester.Properties.Settings> 
      <setting name="SettingSomething" serializeAs="String"> 
      <value>1234</value> 
      </setting> 
     </SnipetTester.Properties.Settings> 
     </applicationSettings> 
    </configuration> 

W kodzie, jestem w stanie uzyskać dostęp do ustawień tak:

Console.WriteLine("Default setting value: " + Properties.Settings.Default.SettingSomething); 

Chodzi o to, że po uruchomieniu aplikacji, powinny być jest w stanie określić plik konfiguracyjny w czasie wykonywania i aplikacja musi załadować plik konfiguracyjny do obiektu Properties.Settings.Default zamiast używać domyślnego pliku app.config. Formaty plików konfiguracyjnych byłyby takie same, ale wartości ustawień byłyby inne.

Wiem sposób, aby to zrobić z ConfigurationManager.OpenExeConfiguration(configFile);. Jednak w testach, które uruchomiłem, nie aktualizuje on obiektu Properties.Settings.Default, aby odzwierciedlić nowe wartości z pliku konfiguracyjnego.


Po myśleć o tym nieco dłużej, udało mi się wymyślić rozwiązanie, które lubię trochę lepiej. Jestem pewna, że ​​ma pewne pułapki, ale myślę, że zadziała, jeśli tego potrzebuję.

Zasadniczo klasa Properties.Settings jest generowana automatycznie przez program Visual Studio; generuje dla ciebie kod dla klasy. Udało mi się znaleźć miejsce wygenerowania kodu i dodać kilka wywołań funkcji, aby samodzielnie załadować plik konfiguracyjny. Oto mój dodatek:

internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 
{ 
    //Parses a config file and loads its settings 
    public void Load(string filename) 
    { 
     System.Xml.Linq.XElement xml = null; 
     try 
     { 
      string text = System.IO.File.ReadAllText(filename); 
      xml = System.Xml.Linq.XElement.Parse(text); 
     } 
     catch 
     { 
      //Pokemon catch statement (gotta catch 'em all) 

      //If some exception occurs while loading the file, 
      //assume either the file was unable to be read or 
      //the config file is not in the right format. 
      //The xml variable will be null and none of the 
      //settings will be loaded. 
     } 

     if(xml != null) 
     { 
      foreach(System.Xml.Linq.XElement currentElement in xml.Elements()) 
      { 
       switch (currentElement.Name.LocalName) 
       { 
        case "userSettings": 
        case "applicationSettings": 
         foreach (System.Xml.Linq.XElement settingNamespace in currentElement.Elements()) 
         { 
          if (settingNamespace.Name.LocalName == "SnipetTester.Properties.Settings") 
          { 
           foreach (System.Xml.Linq.XElement setting in settingNamespace.Elements()) 
           { 
            LoadSetting(setting); 
           } 
          } 
         } 
         break; 
        default: 
         break; 
       } 
      } 
     } 
    } 

    //Loads a setting based on it's xml representation in the config file 
    private void LoadSetting(System.Xml.Linq.XElement setting) 
    { 
     string name = null, type = null, value = null; 

     if (setting.Name.LocalName == "setting") 
     { 
      System.Xml.Linq.XAttribute xName = setting.Attribute("name"); 
      if (xName != null) 
      { 
       name = xName.Value; 
      } 

      System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs"); 
      if (xSerialize != null) 
      { 
       type = xSerialize.Value; 
      } 

      System.Xml.Linq.XElement xValue = setting.Element("value"); 
      if (xValue != null) 
      { 
       value = xValue.Value; 
      } 
     } 


     if (string.IsNullOrEmpty(name) == false && 
      string.IsNullOrEmpty(type) == false && 
      string.IsNullOrEmpty(value) == false) 
     { 
      switch (name) 
      { 
       //One of the pitfalls is that everytime you add a new 
       //setting to the config file, you will need to add another 
       //case to the switch statement. 
       case "SettingSomething": 
        this[name] = value; 
        break; 
       default: 
        break; 
      } 
     } 
    } 
} 

Kod dodałem naraża funkcję Properties.Settings.Load(string filename). Funkcja przyjmuje nazwę pliku konfiguracyjnego jako parametr. Sparuje plik i załaduje wszystkie ustawienia, które napotka w pliku konfiguracyjnym. Aby powrócić do pierwotnej konfiguracji, po prostu zadzwoń pod numer Properties.Settings.Reload().

Mam nadzieję, że to pomoże komuś innemu!

+0

wydaje się to bardzo obiecujące, ale jak możemy użyć typów – tofutim

Odpowiedz

0

Zobacz, jak używać ExeConfigurationFileMap i ConfigurationManager.OpenMappedExeConfiguration.

Zobacz Cracking the Mysteries of .Net 2.0 Configuration

ExeConfigurationFileMap pozwala na specjalnie skonfigurować dokładnych ścieżek do maszyny, exe, roaming i lokalnych konfiguracja plików, wszyscy razem, albo fragmentaryczne, podczas wywoływania OpenMappedExeConfiguration(). Nie jest wymagane określenie wszystkich plików , ale wszystkie pliki zostaną zidentyfikowane i scalone po utworzeniu obiektu konfiguracyjnego . Podczas korzystania z konfiguracji OpenMappedExeConfiguracja , ważne jest, aby zrozumieć, że wszystkie poziomy konfiguracji na poziomie, o który prosisz, będą zawsze łączone . Jeśli podasz niestandardowy plik konfiguracji exe i lokalny, , ale nie określisz komputera i pliku mobilnego, pliki domyślne komputera i pliki roamingowe zostaną znalezione i scalone z określonymi plikami exe i użytkownikami . Może to mieć nieoczekiwane konsekwencje, jeśli określone pliki nie będą prawidłowo zsynchronizowane z plikami domyślnymi.

1

To zależy od rodzaju aplikacji:

  1. Web Application & aplikacji Windows - użyć atrybutu configSource xml, jeśli są chętni do przechowywania plików konfiguracyjnych w tym samym folderze (lub podfolderami) jako Aplikacja
  2. Utwórz settings provider, a także zaimplementuj.... Próbki here i here. Może być również konieczne użycie interfejsu IConfigurationManagerInternal w celu zastąpienia domyślnego menedżera konfiguracji .NET. Podczas implementacji dostawcy nie zapomnij wprowadzić różnic między ustawieniami użytkownika a ustawieniami aplikacji i profilami mobilnymi.

Jeśli chcesz szybko rozpocząć pracę właśnie dekompilować klasy LocalFileSettingsProvider (dostawcę ustawienia domyślne) i zmienić go do swoich potrzeb (można znaleźć jakiś kod useles i może trzeba powielać wszystkich klas, na których zależy).

Powodzenia

0

Można to typy, dzięki czemu nie trzeba ręcznie zaktualizować source za każdym razem.

`private void LoadSetting (ustawienie System.Xml.Linq.XElement) { ciąg name = null, type = null; string value = null;

 if (setting.Name.LocalName == "setting") 
     { 
      System.Xml.Linq.XAttribute xName = setting.Attribute("name"); 
      if (xName != null) 
      { 
       name = xName.Value; 
      } 

      System.Xml.Linq.XAttribute xSerialize = setting.Attribute("serializeAs"); 
      if (xSerialize != null) 
      { 
       type = xSerialize.Value; 
      } 

      System.Xml.Linq.XElement xValue = setting.Element("value"); 
      if (xValue != null) 
      { 
       if (this[name].GetType() == typeof(System.Collections.Specialized.StringCollection)) 
       { 
        foreach (string s in xValue.Element("ArrayOfString").Elements()) 
        { 
         if (!((System.Collections.Specialized.StringCollection)this[name]).Contains(s)) 
          ((System.Collections.Specialized.StringCollection)this[name]).Add(s); 
        } 
       } 
       else 
       { 
        value = xValue.Value; 
       } 

       if (this[name].GetType() == typeof(int)) 
       { 
        this[name] = int.Parse(value); 
       } 
       else if (this[name].GetType() == typeof(bool)) 
       { 
        this[name] = bool.Parse(value); 
       } 
       else 
       { 
        this[name] = value; 
       } 

      } 
     }` 
+0

czy możliwe jest obsłużenie tego dla dowolnego typu – tofutim

Powiązane problemy