Storing a collection in the App.config appSettings

Merrion

Junior Contributor
Joined
Sep 29, 2001
Messages
265
Location
Dublin, Ireland
OK - I have an App.config file and am able to read single items in name/value pairs thus:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
      <!-- Monitor level...1=Max, 2=Min, 3=None-->
      <add key="MonitorJobEventInformationLevel" value="1"/>
      <!-- Monitor Printer Change Events? 0=No, -1 = Yes -->
      <add key="MonitorPrinterChangeEvent" value="-1"/>
      <!-- Monitor Job Added Events? 0=No, -1 = Yes -->
      <add key="MonitorJobAddedEvent" value="-1"/>
      <!-- Monitor Job Deleted Events? 0=No, -1 = Yes -->
      <add key="MonitorDeletedEvent" value="-1"/>
      <!-- Monitor Job Set Events? 0=No, -1 = Yes -->
      <add key="MonitorJobSetEvent" value="-1"/>
      <!-- Monitor Job Written Events? 0=No, -1 = Yes -->
      <add key="MonitorJobWrittenEvent" value="-1"/>
   </appSettings>
</configuration>

which is accessed by:
Visual Basic:
Dim foo As Integer = System.Configuration.AppSettings.GetSetting("MonitorJobEventInformationLevel")

But I also have a collection (of printer names, for example) and I want to store and access this in the config file. How can this be done?

Currently I have a workaround which is:
Code:
      <add key="MonitoredPrintersCount" value="2"/>
      <add key="MonitoredPrinter1" value="HP LaserJet 5L"/>
      <add key="MonitoredPrinter2" value="Microsoft Office Document Image Writer"/>

but I would prefer a more XML approach e.g.:
Code:
      <monitoredprinters>
         <add DeviceName="HP LaserJet 5L"/>
         <add DeviceName="Microsoft Office Document Image Writer"/>
      </monitoredprinters>

Thanks in advance,
Duncan
 
As far as I know it's not possible using the AppSettingReader class or similar. I'd recommend making your own serializable class an then serializing/deserializing that with the System.Xml.Serialization namespace to read your settings. That's far more flexible than just simple strings.
 
That seems to be the concencus - thanks. I was just worried I'd missed something obvious before going down the route of writing my own ConfigReader.
 
Thus if the config file is like:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
      <!-- Extra custom configuration sections -->
      <section name="monitoredPrinters"            type="PrinterMonitorService.CustomConfigurationSectionReaders.MonitoredPrintersSectionReader, PrinterMonitorService" />         
   </configSections>
       
    <monitoredPrinters>
         <!-- DeviceName = The unique name by which the printer is known
           -->
         <monitoredPrinter DeviceName="HP LaserJet 5L"/>
         <monitoredPrinter DeviceName="Microsoft Office Document Image Writer"/>
    </monitoredPrinters>
      
</configuration>

Then the class to read it could look like:-
Code:
    Public NotInheritable Class MonitoredPrintersSectionReader
        Implements IConfigurationSectionHandler

#Region "Private constants"
        Private Const SECTION_NAME As String = "monitoredPrinters"
        Private Const ATTRIBUTE_NAME As String = "monitoredPrinter"
#End Region

        Shared Sub New()
            ConfigurationSettings.GetConfig(SECTION_NAME)
        End Sub

        Public Shared Function GetMonitoredPrintersCollection() As Collection
            Return CType(System.Configuration.ConfigurationSettings.GetConfig(SECTION_NAME), Collection)
        End Function

#Region "IConfigurationSectionHandler interface"
        Public Function Create( _
                 ByVal parent As Object, _
                 ByVal configContext As Object, _
                 ByVal section As XmlNode _
                 ) As Object Implements IConfigurationSectionHandler.Create


            Dim retVal As New Collection()

            If section.HasChildNodes Then
                Dim childNode As XmlNode
                For Each childNode In section.ChildNodes
                    If childNode.Name = ATTRIBUTE_NAME Then
                        retVal.Add(childNode.Attributes.ItemOf("DeviceName").Value)
                    End If
                Next
            End If

            Return retVal
        End Function
#End Region

        Private Sub New()
            '\\ make this class non creatable
        End Sub
    End Class

Hope this is useful,
Duncan
 
You should just be able to create a class with the Serializable() attribute, and use the XmlSerializer class to automatically serialize/deserialize it to and from disk. That way you don't even need to "read" the key from the file, you can just deserialize the file into the class, and then use the properties of the class to get what you need.

As long as you store the printers (in your class) using a collection which is Serializable(), you can add the printers to the collection, and they will be correctly stored and retreived upon (de)serialization. In your case, you would need it to serialize a collection of monitoredPrinter objects, each with a DeviceName property.
 
True - in fact I'm not sure what extra functionality deriving the class form IConfigurationSectionHandler gives - but I have posted the resultant printer monitor service here if you want a shufti at the code.
 
Back
Top