Whenever we develop an application we have to make that application more configurable. To develop any application as configurable we have to save common application settings and data like file paths in the App.config (for windows) or Web.config/Machine.config (for web) or in some other file which stores in the shared location. And we have to access all config settings in a safe manner from the configuration file. In my previous article Create & Read Custom Section Handlers in C# using IConfigurationSectionHandler, I explained about how to access the config data from App.config file which is the configuration file for the application. In this article we will discuss about how to access configuration data in C# from the external configuration file using Microsoft Enterprise Library FileConfigurationSource.
First we have to download Enterprise Library 5.0.msi for Microsoft Enterprise Library version 5.0 from https://www.microsoft.com/en-us/download/details.aspx?id=15104 and install it. It installs the enterprise dlls in C:\Program Files (x86)\Microsoft Enterprise Library 5.0\Bin (for 64-bit machine) and C:\Program Files\Microsoft Enterprise Library 5.0\Bin (for 32-bit machine).
Open Microsoft Visual Studio 2015 => Select Windows Forms Application form the project templates and name it as CSharpFileConfigurationSource. Add reference to the System.Configuration as shown below.
Now add reference for Microsoft.Practices.EnterpriseLibrary.Common.dll from installation folder C:\Program Files (x86)\Microsoft Enterprise Library 5.0\Bin as shown below.
Create some config file in accessible location and save it is external.config as shown below. We have saved the file in E drive so the file path is E:\external.config.
external.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Data" type="CSharpFileConfigurationSource.ReportConfig, CSharpFileConfigurationSource" />
</configSections>
<Data>
<Reports>
<Report Name="Report1">
<FileName>Report1.csv</FileName>
<FolderPath>C:\Reports\</FolderPath>
</Report>
<Report Name="Report2">
<FileName>Report2.csv</FileName>
<FolderPath>C:\Reports\</FolderPath>
</Report>
</Reports>
</Data>
</configuration>
Create the Report.cs, ReportCollection.cs, and ReportConfig.cs classes to access the Data section from external.config file as shown below.
Report.cs
using System.Configuration;
namespace CSharpFileConfigurationSource
{
public class Report : ConfigurationElement
{
[ConfigurationProperty("Name", IsRequired = true)]
public string Name { get { return (string)base["Name"]; } }
[ConfigurationProperty("FileName")]
public ConfigurationTextElement<string> FileName
{ get { return (ConfigurationTextElement<string>)base["FileName"]; } }
[ConfigurationProperty("FolderPath")]
public ConfigurationTextElement<string> FolderPath
{ get { return (ConfigurationTextElement<string>)base["FolderPath"]; } }
[ConfigurationProperty("Reports")]
public ReportCollection Reports { get { return (ReportCollection)base["Reports"]; } }
}
}
ReportCollection.cs
using System.Configuration;
namespace CSharpFileConfigurationSource
{
[ConfigurationCollection(typeof(Report), AddItemName = "Report", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class ReportCollection : ConfigurationElementCollection
{
public ConfigurationElementCollectionType CollectionType
{ get { return ConfigurationElementCollectionType.BasicMap; } }
protected override string ElementName
{ get { return "Report"; } }
protected override ConfigurationElement CreateNewElement()
{ return new Report(); }
protected override object GetElementKey(ConfigurationElement element)
{ return (element as Report).Name; }
public Report this[int index]
{
get { return (Report)base.BaseGet(index); }
set
{
if (base.BaseGet(index) != null)
{
base.BaseRemoveAt(index);
}
base.BaseAdd(index, value);
}
}
public Report this[string title]
{ get { return (Report)base.BaseGet(title); } }
}
}
ReportConfig.cs
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Configuration;
namespace CSharpFileConfigurationSource
{
public class ReportConfig : ConfigurationSection
{
private static ReportConfig current;
private static readonly object singleton = new object();
/// <summary>
/// read instance by using Singleton design pattern
/// </summary>
private static ReportConfig Instance
{
get
{
if (ReportConfig.current == null)
{
lock (ReportConfig.singleton)
{
if (ReportConfig.current == null)
{
ReportConfig.current = new ReportConfig();
}
}
}
return ReportConfig.current;
}
}
private FileConfigurationSource fileConfigurationSource;
private ReportConfig()
{
this.fileConfigurationSource = new FileConfigurationSource(@"E:\external.config");
}
public static ReportConfig Settings { get { return (ReportConfig)ReportConfig.Instance.fileConfigurationSource.GetSection("Data"); } }
[ConfigurationProperty("Reports")]
public ReportCollection Reports { get { return (ReportCollection)base["Reports"]; } }
}
}
As shown above we are using FileConfigurationSource class to access the external.config file. FileConfigurationSource class available in Microsoft.Practices.EnterpriseLibrary.Common.Configuration namespace. In Report.cs class we used the ConfigurationTextElement custom class to access the XML elements data from external.config file, the definition of the ConfigurationTextElement is as shown below.
ConfigurationTextElement.cs
using System.Configuration;
namespace CSharpFileConfigurationSource
{
public class ConfigurationTextElement<T> : ConfigurationElement
{
private T _value;
protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey)
{
_value = (T)reader.ReadElementContentAs(typeof(T), null);
}
public T Value
{
get { return _value; }
set { _value = value; }
}
}
}
Access the reports from the external.config file by calling ReportConfig class as shown below.
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System;
using System.Windows.Forms;
namespace CSharpFileConfigurationSource
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string sReportNames = "Report Names: ";
string sFileNames = "File Names: ";
string sFolderPaths = "Folder Paths: ";
foreach (Report report in ReportConfig.Settings.Reports)
{
sReportNames = sReportNames + report.Name + ", ";
sFileNames = sFileNames + report.FileName.Value + ", ";
sFolderPaths = sFolderPaths + report.FolderPath.Value + ", ";
}
MessageBox.Show("Reports Data: " + Environment.NewLine + Environment.NewLine
+ sReportNames + Environment.NewLine + sFileNames + Environment.NewLine + sFolderPaths);
}
}
}
Run the solution and it displays the output as shown below.
In this way we can access configuration settings from the external file by using FileConfigurationSource class.