Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Read a Configuration Section from XML in a Database?

I have a Config class like this:

public class MyConfig : ConfigurationSection {         [ConfigurationProperty("MyProperty", IsRequired = true)]         public string MyProperty         {             get { return (string)this["MyProperty"]; }             set { this["MyProperty"] = value; }         } } 

And it is being instantiated by another class like this

(MyConfig)ConfigurationManager.GetSection("myConfig") 

We are making some changes and are now storing the configuration file in the DB as an xml, exactly like it is currently in the config file.

I would like to maintain the MyConfig as a ConfigurationSection for backwards compatibility but still be able to instantiate it by using the XML string retrieved from the DB.

Is it possible? If so, how? (Keep in mind it should still work as instantiated above)

like image 249
Jonas Stawski Avatar asked Dec 02 '10 19:12

Jonas Stawski


2 Answers

Here is how I usually do it: just add these members to the MyConfig class:

    public class MyConfig : ConfigurationSection     {         private static MyConfig _current;         public static MyConfig Current         {             get             {                 if (_current == null)                 {                     switch(ConfigurationStorageType) // where do you want read config from?                     {                         case ConfigFile: // from .config file                             _current = ConfigurationManager.GetSection("MySectionName") as MyConfig;                             break;                          case ConfigDb: // from database                         default:                             using (Stream stream = GetMyStreamFromDb())                             {                                 using (XmlTextReader reader = new XmlTextReader(stream))                                 {                                     _current = Get(reader);                                 }                             }                             break;                       }                 }                 return _current;             }         }          public static MyConfig Get(XmlReader reader)         {             if (reader == null)                 throw new ArgumentNullException("reader");              MyConfig section = new MyConfig();             section.DeserializeSection(reader);             return section;         }     } 

This way, you have nothing to change in the MyConfig class, but you still need to change the way your customers access it with this kind of code:

string myProp = MyConfig.Current.MyProperty; 
like image 194
Simon Mourier Avatar answered Sep 21 '22 16:09

Simon Mourier


If you need to get any System.Configuration.ConfigurationSection stored in database, you may consider writing generic section reader like this:

      public class ConfigurationSectionReader where T : ConfigurationSection, new() {     public T GetSection( string sectionXml )      {         T section = new T();         using ( StringReader stringReader = new StringReader( sectionXml ) )         using ( XmlReader reader = XmlReader.Create( stringReader, new XmlReaderSettings() { CloseInput = true } ) )         {             reader.Read();             section.GetType().GetMethod( "DeserializeElement", BindingFlags.NonPublic | BindingFlags.Instance ).Invoke( section, new object[] { reader, true } );         }         return section;     } }      

This will work for all classes that override DeserializeElement method. e.g.

      protected override void DeserializeElement( XmlReader reader, bool serializeCollectionKey ) {     XmlDocument document = new XmlDocument();     document.LoadXml( reader.ReadOuterXml() );     MyProperty = document.DocumentElement.HasAttribute( "MyProperty" )         ? document.DocumentElement.Attributes[ "MyProperty" ].Value         : string.Empty; }      

Than you could get a section like this:

      var reader = new ConfigurationSectionReader(); var section = reader.GetSection( sectionXml ); // where sectionXml is the XML string retrieved from the DB      
like image 33
Rest Wing Avatar answered Sep 22 '22 16:09

Rest Wing