Introduction
The use of configuration file is a crucial aspect to modify applications behaviour without changing the internal code. In .NET, there are powerful features to manage the settings file in XML format. The use of application setting composed of a couple name value attributes is immediate! When you try to implement your custom configuration file for your business logic starts the trouble. In this article, I present a solution to structure nested element in a separate configuration file.
External File
In order to have a separate configuration file to make distinct configuration for different parts of the application, I add the following code into the app.config:
<sectionGroup name="customSectionGroup" type="ecoLDS_HMI.CustomConfigSectionGroup,
ecoLDS_HMI">
<section name="customUserSettings" type="ecoLDS_HMI.CustomConfigSection, ecoLDS_HMI"/>
</sectionGroup>
<customSectionGroup >
<customUserSettings configSource="UserSettings.config" />
</customSectionGroup>
Specifying the configuration source, the custom user settings are stored in a separate file called UserSettings.config.
Custom .config File
In the UserSetting.config file, I stored my custom configuration composed of zooms node as root element and a sequence of zoomLine node with inside sequence of zoomZone. I use this type of configuration file to set up my map component for a different level of zoom depending on the structure of the line.
<customUserSettings userName="Enrico" expiresOn="10/10/2017" >
<zooms>
<zoomLine numLinea="1">
<zones>
<zoomZone numNode="1" zoomValue="200"/>
<zoomZone numNode="5" zoomValue="300"/>
</zones>
</zoomLine>
<zoomLine numLine="2" >
<zones>
<zoomZone numNode="1" zoomValue="200"/>
<zoomZone numNode="2" zoomValue="200"/>
</zones>
</zoomLine>
</zooms>
</customUserSettings>
Implementation
In order to read my config file UserSetting.config I exploited the System.Configuration library of .NET Framework extending the class ConfigurationSection, ConfigurationElementCollection and ConfigurationElement.
To read the section represented by the node customUserSettings with the two attributes userName and expiresOn, I extended the class ConfigurationSection adding a configuration property for each attribute and for the sub element zooms.
Public Class CustomConfigSection
Inherits ConfigurationSection
Public Sub New()
End Sub
<ConfigurationProperty("userName")> _
Public Property UserName() As String
Get
Return CType(Me("userName"), String)
End Get
Set(ByVal value As String)
Me("userName") = value
End Set
End Property
<ConfigurationProperty("expiresOn")> _
Public Property ExpiresOn() As String
Get
Return CType(Me("expiresOn"), String)
End Get
Set(ByVal value As String)
Me("expiresOn") = value
End Set
End Property
<ConfigurationProperty("zooms")> _
Public ReadOnly Property CustomConfigElementCollection() As ZoomLineCollection
Get
Return TryCast(Me("zooms"), ZoomLineCollection)
End Get
End Property
End Class
The last configuration property zooms contain a list of ZoomLine elements collected in a collection called ZoomLineCollection.
The class implemented to read the ZoomLine element extends ConfiguarationElement class. We have added a configuration property for each attribute and a configuration property for the element zones following the previous pattern.
The zones configuration property contain a collection of zone element.
Public Class ZoomLine
Inherits ConfigurationElement
<ConfigurationProperty("numLine", DefaultValue:="0", IsKey:=True)> _
<IntegerValidator(MinValue:=0, MaxValue:=200)> _
Public Property NumLinea() As Integer
Get
Return CType(Me("numLine"), Integer)
End Get
Set(ByVal value As Integer)
Me("numLine") = value
End Set
End Property
<ConfigurationProperty("zones")> _
Public ReadOnly Property CustomConfigElementCollection() As ZoomZonesCollection
Get
Return TryCast(Me("zones"), ZoomZonesCollection)
End Get
End Property
End Class
The class ZoomLineCollection extends ConfigurationElementCollection class and reads the sequence of zoomLine elements. The declarative configuration AddItemName:="zoomLine" connects the XML node with the corresponding class that composed the collection in this case zoomLine.
<ConfigurationCollection(GetType(ZoomLinea), AddItemName:="zoomLine")> _
Public Class ZoomLineCollection
Inherits ConfigurationElementCollection
Protected Overrides Function CreateNewElement() As ConfigurationElement
Return New ZoomLinea()
End Function
Public Sub Add(ByVal valueInteger As Integer)
Dim newElement As ZoomLinea = TryCast(Me.CreateNewElement(), ZoomLine)
newElement.NumLine = valueInteger
MyBase.BaseAdd(newElement)
End Sub
Protected Overrides Function GetElementKey_
(ByVal element As System.Configuration.ConfigurationElement) As Object
Dim elem As ZoomLine = TryCast(element, ZoomLine)
Return elem.NumLinea
End Function
End Class
The remaining two classes to read and collect the zoomZone elements follow the structure of the previous one.
Public Class ZoomZone
Inherits ConfigurationElement
<ConfigurationProperty("numNode", DefaultValue:="-1", _
IsKey:=False, IsRequired:=False)> _
Public Property NumNode() As Integer
Get
Return CType(Me("numNode"), Integer)
End Get
Set(ByVal value As Integer)
Me("numNode") = value
End Set
End Property
<ConfigurationProperty("zoomValue", DefaultValue:="100", _
IsKey:=False, IsRequired:=False)> _
<IntegerValidator(MinValue:=100, MaxValue:=500)> _
Public Property ZoomValue() As Integer
Get
Return CType(Me("zoomValue"), Integer)
End Get
Set(ByVal value As Integer)
Me("zoomValue") = value
End Set
End Property
End Class
<ConfigurationCollection(GetType(ZoomZone), AddItemName:="zoomZone")> _
Public Class ZoomZonaCollection
Inherits ConfigurationElementCollection
Protected Overrides Function CreateNewElement() As ConfigurationElement
Return New ZoomZone()
End Function
Public Sub Add(ByVal valueString As String, ByVal valueInteger As Integer)
Dim newElement As ZoomZona = TryCast(Me.CreateNewElement(), ZoomZone)
newElement.NumNode = valueString
newElement.ZoomValue = valueInteger
MyBase.BaseAdd(newElement)
End Sub
Protected Overrides Function GetElementKey_
(ByVal element As System.Configuration.ConfigurationElement) As Object
Dim elem As ZoomZona = TryCast(element, ZoomZone)
Return elem.NumNode
End Function
End Class
Conclusion
The .NET configuration library provides useful features that need to be discovered, as the declarative specification of the configuration properties.
To implement the nested element, I followed these two rules:
- For each sequence of elements, I implemented a collection.
- For each node, I implemented a configuration element class with a configuration property
- for each attribute
- for each child node
History
- 5th October, 2010: Initial post