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