Category Archives: Configuration

Cinchoo – Application configuration made easy

1. Introduction

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

Cinchoo – Application configuration is one of the feature Cinchoo framework provides for the developer.  Application configuration is the information that application reads/writes at run time from the source. .NET already provides extensive support through several predefined configuration section handlers for the developers. But require some pluming development work on top of them to complete the exercise.

Cinchoo framework simply them with less code and read/write configuration values to the underlying data sources seamlessly. Also it gives you the flexibility of interchanging the configuration sources through configuration without any code change. In the following sections, I’m going to provide you in detail on how to use them in your application.

Cinchoo configuration framework have the below powerful features

  • One single API to deal with configuration data with multiple sources
  • Two-way, type-safe configuration management
  • Create the configuration files, if those are missing
  • Generate the configuration sections, if not exists
  • During application run time, has the flexibility of changing the configuration sources without any restart or downtime needed.
  • Auto correct the section if it missing any entries in the configuration files.

2. Requirement

This configuration library is written in C# for the .NET 4.0 Framework. It is part of Cinchoo framework, which is a great library with lot of features like Configuration Management, common ApplicationHost, Shell features, etc.

3. “Hello World!” Sample

Let’s begin by looking into a simple example of an application consuming two configuration values name and message. name is required configuration value and msg is optional configuration value with default value 100, Madison Avenue, New York, NY 10010“. If msg is not configured, it will take the default value.

  • Download the latest Cinchoo binary here. (Nuget Command: Install-Package Cinchoo)
  • Open VS.NET 2010 or higher
  • Create a sample VS.NET (.NET Framework 4) Console Application project
  • Add reference to Cinchoo.Core.dll
  • Use the Cinchoo.Core and Cinchoo.Core.Configuration namespace
  • Copy and paste the below command line object
Namespace: Cinchoo.Core.Configuration

The heart of the Cinchoo configuration framework is in Cinchoo.Core.Configuration namespace. This namespace is available when you reference Cinchoo.Core.dll assembly in your project.

PS: Please turn on Reflection Permission in order to use this framework.

Listing 3.1 Defining Configuration Object

[ChoNameValueConfigurationSection("appSettings")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name", DefaultValue = "Mark")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

By default, all public properties and fields will be treated as configuration properties. Each class member may be decorated using ChoPropertyInfoAttribute with the property name, default value, fallback value etc. Framework binds the members to the configuration attributes by the name.

The code above illustrates about defining configuration object. First thing define a configuration (ex. AppSettings) class from ChoConfigurableObject, it indicates that this object is a configuration object. And it must be decorated with one of the available configuration section attributes, will be discussed later. In this example, I’ve used ChoNameValueConfigurationSectionAttribute with appSettings as section name to complete the definition. It specifies that this configuration section is the NameValueConfigurationSection. With this definition, we turned the above configuration object provides name/value-pair configuration information from a configuration section.

Define configuration value members Name and Address either as public fields or properties with get and set in it. Decorate them with ChoPropertyInfo attribute to indicate that they are configuration members. In this sample, Name is the optional configuration member. It is given nameas configuration member name with the DefaultValue as Mark‘. It means that if the configuration value is missing from the source, it will be defaulted to DefaultValue.

Address configuration member is an optional member as well. It was given with addressas name with DefaultValue as 100, Madison Avenue, New York, NY 10010.

Once you have the configuration object defined as above, it is now ready to use in your application. Here is how you can create and use it.

Listing 3.2 Main Method

static void Main(string[] args)
{
    AppSettings appSettings = new AppSettings();
    Console.WriteLine(appSettings.ToString());

    //Update the name to 'Raj', see it is updating to source
    appSettings.Name = "Raj";

    ChoConsole.PauseLine();
}

We start by creating a new instance of AppSettings object, That’s all. All the heavy lifting of loading configuration values to the object is done by the framework under the hood.

Now compile this program and run. It will create the section in [appExeName].xml (HelloWorld.exe.xml) file under bin/Config folder.

Listing 3.3 HelloWorld.exe.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, 
       Cinchoo.Core, Version=1.0.1.1, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
  <appSettings>
    <add key="name" value="Raj" />
    <add key="address" value="100, Madison Avenue, New York, NY 10010" />
  </appSettings>
</configuration>

Writing code to provide custom configuration section to your application is very simple and straightforward. Vast bulk of dealing with configuration data is done by Cinchoo framework.

4. Types of Configuration Section Handlers

Cinchoo framework provides some configuration section handlers out of the box. Listed below are few of the available configuration section handlers:

  • ChoNameValueConfigurationSection – Provides name/value pair configuration information from a configuration section.
  • ChoDictionaryConfigurationSection – Provides key/value pair configuration information from a configuration section.
  • ChoSingleTagConfigurationSection – Handles configuration sections that are represented by a single XML tag in the configuration file.
  • ChoStandardAppSettingsConfigurationSection – Read/Write Key/Value pair from <appSettings> section
  • ChoIniConfigurationSection – Read/Write configuration values from INI files.
  • ChoRegistryConfigurationSection – Read/Write configuration values from System Registry.
  • ChoDbGenericKeyValueConfigurationSection – Read/Write configuration values from any databases.

4.1 ChoNameValueConfigurationSection

It provides access to name/value pair configuration information from configuration section. It uses NameValueCollection as the underlying storage, it means that values its stores are string->string pairs. It provides simple solutions, if you need a configuration to be efficient use ChoDictionaryConfigurationSection.

The below example illustrates how to define and use this section to consume the configuration values. Declare ChoNameValueConfigurationSectionAttribute to the configuration class to use this section handler.

Listing 4.1.1 Defining Configuration Object

[ChoNameValueConfigurationSection("appSettings")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.1.2 HelloWorld.exe.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, 
       Cinchoo.Core, Version=1.0.1.1, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
  <appSettings>
    <add key="name" value="Raj" />
    <add key="address" value="100, Madison Avenue, New York, NY 10010" />
  </appSettings>
</configuration>

4.2 ChoDictionaryConfigurationSection

It provides access to key/value pair configuration information from configuration section. It is very similar to ChoNameValueConfigurationSection, but more efficient to consume configuration values.

The below example illustrates how to define and use this section to consume the configuration values. Declare ChoDictionaryConfigurationSectionAttribute to the configuration class to use this section handler.

Listing 4.2.1 Defining Configuration Object

[ChoDictionaryConfigurationSection("appSettings")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.2.2 HelloWorld.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" type="Cinchoo.Core.Configuration.ChoDictionarySectionHandler, 
       Cinchoo.Core, Version=1.0.1.1, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
  <appSettings>
    <add key="name" value="Raj" />
    <add key="address" value="100, Madison Avenue, New York, NY 10010" />
  </appSettings>
</configuration>

4.3 ChoSingleTagConfigurationSection

It handles configuration sections that are represented by a single XML tag in the configuration file. It is a very simple, elegant way to have values in the configuration file. Only downside is that it can contain only the simple values.

The below example illustrates how to define and use this section to consume the configuration values. Declare ChoSingleTagConfigurationSectionAttribute to the class to use this section handler.

Listing 4.3.1 Defining Configuration Object

[ChoSingleTagConfigurationSection("appSettings")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.3.2 HelloWorld.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" 
    type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core" />
  </configSections>
  <appSettings name="Raj" address="100, Madison Avenue, New York, NY 10010" />
</configuration>

4.4 ChoIniConfigurationSection

It handles the reading and writing of configuration values from INI file, a simple text files with basic structure composed of sections, properties and values. It is supported by some legacy platforms.

Listing 4.4.1 Sample INI file (AppSettings.ini)

; last modified 1 April 2001 by John Doe
[APP_SETTINGS]
NAME=John Doe
ADDRESS=Acme Widgets Inc.
 
[DATABASE]
; use IP address in case network name resolution is not working
SERVER=192.0.2.62     
PORT=143
FILE="payroll.dat"

This section simplifies the consumption of INI file values into configuration object by providing unified interface. The below example illustrates how to define and use this section to consume the INI values. Declare ChoIniConfigurationSectionAttribute to the configuration class to use this section handler.

Listing 4.4.2 Defining Configuration Object

[ChoIniConfigurationSection("appSettings", "APP_SETTINGS", "AppSettings.ini")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

The code above illustrates how the INI configuration section is specified to configuration object. It specifies the name of the INI file (AppSettings.ini) where the values will be consumed from/to. It can be addressed as absolute or relative file path. If the file name is specified without path, configuration manager will be looking for the file in the current executable folder. If the INI file not exists, it will be created automatically, containing all the configuration members with default values.

Besides that, you will have to specify the INI section (‘APP_SETTINGS’) name where all the configuration members values will be loaded from.

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.4.3 HelloWorld.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" 
    type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, 
    Cinchoo.Core" />
  </configSections>
  <appSettings cinchoo:iniSectionName="APP_SETTINGS" 
  cinchoo:iniFilePath="AppSettings.ini" 
    xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
</configuration>

4.5 ChoRegistryConfigurationSection

It handles the reading and writing of configuration values from system registry, a hierarchical database that stored configuration settings and options on Microsoft Windows operating systems.

Listing 4.5.1 Sample Registry image (HelloWorld)

This section simplifies the consumption of registry information into configuration object by providing unified interface. The below example illustrates how to define and use this section to consume the registry values. Declare ChoRegistryConfigurationSectionAttribute to the configuration class to use this section handler.

Listing 4.5.2 Defining Configuration Object

[ChoRegistryConfigurationSection("appSettings", @"HKCU\Software\HelloWorld")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

The code above illustrates how the registry configuration section is specified to configuration object. It specifies the location of the registry key where all the configuration values will be consumed from/to. Framework automatically creates the registry key and sub-keys automatically if not found.

Here are some of the shortcut names for well known registry roots can be used when you defining this section

  1. HKCU – HKEY_CURRENT_USER
  2. HKLM – HKEY_LOCAL_MACHINE
  3. HKCR – HKEY_CLASSESS_ROOT
  4. HKCC – HKEY_CURRENT_CONFIG

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.5.3 HelloWorld.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" type="Cinchoo.Core.Configuration.ChoDictionarySectionHandler, 
    Cinchoo.Core" />
  </configSections>
  <appSettings cinchoo:registryKey="HKCU\Software\HelloWorld" 
    xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
</configuration>

4.6 ChoSqlServerConfigurationSection

It handles the reading and writing of configuration values from Microsoft SqlServer database, a RDBMS from Microsoft designed for enterprise environment. A common widely used database in desktop environment.

This section handler allows multiple applications to store and consume centrally located configuration values.

First and foremost, you must create a configuration table in the targeted database as per the below schema.

Listing 4.6.1 Configuration table

CREATE TABLE APP_SETTINGS
(
    [KEY] VARCHAR (50) NOT NULL,
    VALUE VARCHAR (100),
    PRIMARY KEY ([KEY])
)

The table allows to keep key-value pairs for each configuration members.

The below example illustrates how to define and use this section to consume the configuration values. Declare ChoSqlServerConfigurationSectionAttribute to the class to use this section handler.

Listing 4.6.2 Defining Configuration Object

[ChoSqlServerConfigurationSection("appSettings", 
@"Server=SNYC12345400\XYZKND01;Database=TestDb;Trusted_Connection=True;", "APP_SETTINGS")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

The code above illustrates how the sqlserver configuration section is specified to configuration object. In here, we specified configSectionName, database connection string and table name. TableName is optional. If not specified, framework will try to look for tablename in the name of configuration section object name (AppSettings).

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.6.3 HelloWorld.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" type="Cinchoo.Core.Configuration.ChoDictionarySectionHandler, 
    Cinchoo.Core" />
  </configSections>
  <appSettings cinchoo:configObjectAdapterType=
    "Cinchoo.Core.Configuration.ChoDbGenericKeyValueConfigStorage, Cinchoo.Core" 
    xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework">
    <cinchoo:configObjectAdapterParams 
    xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework">
    <![CDATA[CONNECTION_STRING='Server=WNPCTDVZKN01\MSZKND01;Database=School;
    Trusted_Connection=True;';TABLE_NAME=APP_SETTINGS;PROVIDER_NAMESPACE=System.Data.SqlClient]]>
    </cinchoo:configObjectAdapterParams>
  </appSettings>
</configuration>

Number of ChoSqlServerConfigurationSectionAttribute overloads available to meet different requirements. Most of them are self explanatory. One important overload mentioned below now accepts .NET ConnectionString name as parameter.

Listing 4.6.4 ChoSqlServerConfigurationSectionAttribute Overload

public ChoSqlServerConfigurationSectionAttribute
    (string configElementPath, string connectionStringOrName, string tableName);

For example, if your application is already using database using .NET ConnectionString, you might see the below entries in the application configuration file.

Listing 4.6.5 App.Config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
    </configSections>
    <connectionStrings>
        <add name="TESTDB"
            connectionString="Server=SNYC12345400\XYZKND01;Database=TestDb;
        Trusted_Connection=True;" providerName ="System.Data.SqlClient"/>
    </connectionStrings>
</configuration>

This configuration section leverages this feature by accepting .NET ConnectionString name via parameter to eliminate the duplication of maintaining database connection string in multiple places.

The code below illustrates how to use the above connection string name in configuration object.

Listing 4.6.6 Configuration Object using ConnectionStringName

[ChoSqlServerConfigurationSection("appSettings", @"TESTDB", "APP_SETTINGS")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

Cinchoo framework automatically discovers the connection string from system ConnectionStrings section seamlessly and uses them for consuming configuration values.

4.7 ChoAnyDbConfigurationSection

It handles the reading and writing of configuration values from any database. All you need is the ADO.NET driver for the database you want to work with. This section handler allows multiple applications to store and consume centrally located configuration values.

First and foremost, you must create a configuration table in the targeted database as per the below schema.

Listing 4.6.1 Configuration table

CREATE TABLE APP_SETTINGS
(
    [KEY] VARCHAR (50) NOT NULL,
    VALUE VARCHAR (100),
    PRIMARY KEY ([KEY])
)

The table allows to keep key-value pairs for each configuration members.

The below example illustrates how to define and use this section to consume the configuration values. Declare ChoAnyDbConfigurationSectionAttribute to the class to use this section handler.

Listing 4.6.2 Defining Configuration Object

[ChoAnyDbConfigurationSection("appSettings", @"Data Source=.\SqliteTest.db;Version=3;
    Pooling=True;Max Pool Size=100;", "APP_SETTINGS", "System.Data.SQLite")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

The code above illustrates how to setup the configuration section to use Sqlite database to the configuration object. In here, we specified configSectionName, sqlite database connection string, provideName and tableName.

ProvideName is the database ADO.NET provide name. This parameter is optional. If not specified, ‘System.Data.SqlClient‘ will be used.

TableName is optional. If not specified, framework will try to look for tablename in the name of configuration section object name (AppSettings).

Once you instantiate an object, you are ready to consume the configuration values. The file below shows the layout of the configuration file produced when using this section handler.

Listing 4.6.3 HelloWorld.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="appSettings" type="Cinchoo.Core.Configuration.ChoDictionarySectionHandler, 
    Cinchoo.Core" />
  </configSections>
  <appSettings cinchoo:configObjectAdapterType=
    "Cinchoo.Core.Configuration.ChoDbGenericKeyValueConfigStorage, Cinchoo.Core" 
    xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework">
    <cinchoo:configObjectAdapterParams 
    xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework">
    <![CDATA[CONNECTION_STRING='Server=WNPCTDVZKN01\MSZKND01;Database=School;
    Trusted_Connection=True;';TABLE_NAME=APP_SETTINGS;PROVIDER_NAMESPACE=System.Data.SqlClient]]>
    </cinchoo:configObjectAdapterParams>
  </appSettings>
</configuration>

ChoDbAnyConfigurationSectionAttribute now accepts .NET ConnectionString name as parameter via connectionStringOrName.

For example, if your application is already using database using .NET ConnectionString, you might see the below entries in the application configuration file.

Listing 4.6.5 App.Config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
    </configSections>
    <connectionStrings>
        <add name="TESTDB"
            connectionString="Server=SNYC12345400\XYZKND01;Database=TestDb;
        Trusted_Connection=True;" providerName ="System.Data.SqlClient"/>
    </connectionStrings>
</configuration>

This configuration section leverages this feature by accepting .NET ConnectionString name via parameter to eliminate the duplication of maintaining database connection string in multiple places.

The code below illustrates how to use the above connection string name in configuration object.

Listing 4.6.6 Configuration Object using ConnectionStringName

[ChoAnyDbConfigurationSection("appSettings", @"TESTDB", "APP_SETTINGS")]
public class AppSettings : ChoConfigurableObject
{
    [ChoPropertyInfo("name")]
    public string Name;

    [ChoPropertyInfo("address", DefaultValue = "100, Madison Avenue, New York, NY 10010")]
    public string Address;
}

Cinchoo framework automatically discovers the connection string and provides name from system ConnectionStrings section seamlessly and uses them for consuming configuration values.

It is very simple to work with configuration using Cinchoo framework. Try for yourself. Thanks.

Advertisement

Cinchoo – Configuration framework, part 2

Configuration Binding

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this section, we’ll see how the changes are gets exchanged between configuration section object and the configuration file. The binding between them can be controlled either declaratively or through configuration.

Declarative way

BindingMode member of ChoConfigurationSectionAttribute drives the binding nature of the configuration section object. It is of ChoConfigurationBindingMode enum type.

  • TwoWay – (Default) The changes are flown both way between configuration section object and data source.
  • OneWay – The changes are flown only from data source to configuration section object.
  • OneWayToSource – The changes are flown only from configuration section object to data source.
  • OneTime – The configuration settings are read and loaded into configuration section object once. Any changes made either in the configuration section object or data source are not propagated between them.
If none specified, TwoWay  will be the default binding mode.
[ChoConfigurationSection("sample",
	BindingMode = ChoConfigurationBindingMode.TwoWay)]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue = "Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue = "Hello World!")]
	public string Message;

	#endregion
}
Configurable way

You can change the binding mode through configuration anytime without changing the code. Cinchoo framework will give precedence to it over declarative way.

In order to set the binding mode in the configuration, you can do so as below in HelloWorld.config.meta file, usually found in bin/Debug/Config/Meta or bin/Release/Config/Meta folder.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <sample bindingMode="TwoWay" defaultable="true" silent="true">
    <configStorage>Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</configStorage>
    <logInfo condition="true" directory="Settings" fileName="SampleConfigSection.log" />
  </sample>
</configuration>
Let’s see the actions

Now lets write code to change the value of name configuration property to ‘Tommy’, see it is saved to configuration file (Look at the HelloWorld.exe.xml under bin/Debug/Config or bin/Release/Config folder).

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		sampleConfigSection.Name = "Tommy";

		Console.WriteLine("Press ENTER key to exit...");
		Console.ReadLine();
	}
}

After running this sample, you will find that the HelloWorld.exe.xml gets updated as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.Handlers.ChoNameValueSectionHandler, Cinchoo.Core">
        <metaData bindingMode="TwoWay" />
	</section>
  </configSections>
  <sample>
    <add key="name" value="Tommy" />
    <add key="message" value="Hello World!" />
  </sample>
</configuration>

Finally, lets get to see how the changes made to configuration file are loaded to the configuration section object. In order to see the loaded values, I’m going to override OnAfterConfigurationObjectLoaded method as below. This overridden method gets called whenever the object gets loaded with new values.

[ChoConfigurationSection("sample",
	BindingMode = ChoConfigurationBindingMode.TwoWay)]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

    protected override void OnAfterConfigurationObjectLoaded()
    {
        Console.WriteLine(ToString());
    }
}

One another way to see the values of loaded configuration values, you will need to add a OnAfterConfigurationObjectLoaded method to the configuration section class as below, so that it will get triggered as soon as the section gets changed its state. This method should be decorated with ChoAfterConfigurationObjectLoadedHandlerAttribute in order to register with framework.

[ChoConfigurationSection("sample",
	BindingMode = ChoConfigurationBindingMode.TwoWay)]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

Run this sample, and change the name configuration property value to ‘Cathy’ in the configuration file (HelloWorld.exe.xml). You will notice that the configuration section object gets reflected with new value as below

-- HelloWorld.SampleConfigSection State --
        Name: Tommy
        Message: Hello World?

Press ENTER key to exit...
-- HelloWorld.SampleConfigSection State --
        Name: Cathy
        Message: Hello World?
Conclusion
In this section we learned about the binding mode, how and where to specify it, and finally we saw how the changes are exchanged between configuration section object and configuration file.

Cinchoo – Configuration framework, part 3

Configuration file discovery

In this section, I’ll walk you over the discovery of the configuration file by Cinchoo framework. By default, Cinchoo framework creates or uses [appExeName].xml as the application configuration file.

In some cases, you may want to override this behavior and pass the application configuration file explicitly.

Configurable Way

Open App.config file under source directiory, add appFrxSettings custom section as below (absolute or relative path can be specified)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="appFrxSettings" type="Cinchoo.Core.ChoAppFrxSettings, Cinchoo.Core" />
    </configSections>
    <appFrxSettings appFrxFilePath="C:\ConfigFolder" />
</configuration>

Programmatic Way 

Register to ChoApplication.AfterAppFrxSettingsLoaded event to override the application configuration path. Example below

class Program
{
	static void Main(string[] args)
	{
            ChoApplication.AfterAppFrxSettingsLoaded += ((s, e) =&amp;gt;
                {
                    if (e.Value is ChoAppFrxSettings)
                    {
                        ChoAppFrxSettings z = e.Value as ChoAppFrxSettings;
                        z.AppFrxFilePath = @"C:\Config";
                    }
                }
            );
	}
}

PS: Make sure these initializations happens at the application entry point. In Windows Service, the event subscriptions are done at OnStart() method in ServiceBase subclass. In ASP.NET, the subscriptions are done in Application_Start() in Global.aspx file.

Cinchoo – Configuration framework, part 4

Using ChoFileNameValueConfigStorage

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this part, I’ll go over the details of using ChoFileNameValueConfigStorage in your application. It provides name/value-pair configuration information from file source. This is the default configuration storage used by ChoNameValueConfigurationSectionHandlerChoNameValueConfigurationSectionAttribute is the corresponding attribute used to decorate the configuration object class.

1. Define the configuration section object decorated with ChoNameValueConfigurationSectionAttribute as below.

[ChoNameValueConfigurationSection("sample")]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

2. Now instantiate and use it as below

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		Console.WriteLine(sampleConfigSection.ToString());
	}
}

The configuration section will be generated automatically for the first time in HelloWorld.exe.xml as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core" />
  </configSections>
  <sample>
    <add key="name" value="Mark" />
    <add key="message" value="Hello World!" />
  </sample>
</configuration>

Cinchoo – Configuration framework, part 5

Using ChoFileDictionaryConfigStorage

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this section, I’ll go over the details of using ChoFileDictionaryConfigStorage in your application. It provides key/value-pair configuration information from a file source. It is the default storage used by ChoDictionaryConfigurationHandler.

1. Define the configuration section object decorated with ChoDictionaryConfigurationSectionAttribute as below.

[ChoDictionaryConfigurationSection("sample")]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

2. Now instantiate and use it as below.

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		Console.WriteLine(sampleConfigSection.ToString());
	}
}

The configuration section will be generated automatically for the first time in HelloWorld.exe.xml as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoDictionarySectionHandler, Cinchoo.Core" />
  </configSections>
  <sample>
    <add key="name" value="Mark" />
    <add key="message" value="Hello World!" />
  </sample>
</configuration>

Cinchoo – Configuration framework, part 6

Using ChoSingleTagConfigStorage

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this section, I’ll go over the details of using ChoSingleTagConfigStorage in your application. The configuration sections are represented by a single XML tag from a file source.

1. Define the configuration section object decorated with ChoSingleTagConfigurationSectionAttribute as below.

[ChoSingleTagConfigurationSection("sample")]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

2. Now instantiate and use it as below.

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		Console.WriteLine(sampleConfigSection.ToString());
	}
}

The configuration section will be generated automatically for the first time in HelloWorld.exe.xml as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core" />
  </configSections>
  <sample name="Mark" message="Hello World!" />
</configuration>

Cinchoo – Configuration framework, part 7

Using ChoStandardAppSettingsConfigStorage

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this section, I’ll go over the details of using ChoStandardAppSettingsConfigStorage in your application. It’s a custom configuration section handler provides the ability to read and write  custom application key/value-pair configuration information under <appSettings> section in App.config file.

1. Define the configuration section object decorated with ChoStandardAppSettingsConfigurationSectionAttribute as below.

[ChoStandardAppSettingsConfigurationSection]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

2. Now instantiate and use it as below.

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		Console.WriteLine(sampleConfigSection.ToString());
	}
}

The configuration section will be generated automatically for the first time in HelloWorld.exe.config (please note that this section is NOT created in HelloWorld.exe.xml file) as below

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="name" value="Mark" />
    <add key="message" value="Hello World!" />
  </appSettings>
</configuration>

Cinchoo – Configuration framework, part 8

Using ChoIniConfigStorage

UPDATE:

Please visit the below code project article for latest updates

Cinchoo – Using INI file as configuration source

 

 

In this section, I’ll go over the details of using ChoIniConfigStorage in your application. It’s a custom configuration section handler enables the applications to read and write its settings from INI file.

1. Define the configuration section object decorated with ChoIniConfigurationSectionAttribute as below.

[ChoIniConfigurationSection("sample", "SAMPLE_INI_SECTION", "Sample.ini")]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

2. Now instantiate and use it.

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		Console.WriteLine(sampleConfigSection.ToString());
	}
}

The configuration section will be generated automatically for the first time in HelloWorld.exe.xml as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <sample cinchoo:iniSectionName="SAMPLE_INI_SECTION" cinchoo:iniFilePath="Sample.ini" xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
</configuration>

The corresponding meta-data looks as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <sample bindingMode="TwoWay" defaultable="true" silent="true">
    <configStorage>Cinchoo.Core.Configuration.ChoIniConfigStorage, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</configStorage>
    <logInfo condition="true" directory="Settings" fileName="ampleConfigSection.log" />
  </sample>
</configuration>

And the corresponding INI file and section will be created automatically if not exists as below

Please visit the CodeProject article below for more detailed information about this storage.

Cinchoo – Using INI file as configuration source

Cinchoo – Configuration framework, part 9

Using ChoRegistryConfigStorage

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this section, I’ll go over the details of using ChoRegistryConfigStorage in your application. It’s a custom configuration section handler enables application to read and write application settings from Windows System Registry.

1. Define the configuration section object decorated with ChoRegistryConfigurationSectionAttribute as below.

[ChoRegistryConfigurationSection("sample", "HKLM/Software/Sample")]
public class SampleConfigSection : ChoConfigurableObject
{
	#region Instance Data Members (Public)

	[ChoPropertyInfo("name", DefaultValue="Mark")]
	public string Name;

	[ChoPropertyInfo("message", DefaultValue="Hello World!")]
	public string Message;

	#endregion

	[ChoAfterConfigurationObjectLoadedHandler]
	void OnAfterConfigurationObjectLoaded(object sender, ChoConfigurationObjectEventArgs e)
	{
		Console.WriteLine(sender.ToString());
	}
}

2. Instantiate and use it as below.

class Program
{
	static void Main(string[] args)
	{
		SampleConfigSection sampleConfigSection = new SampleConfigSection();
		Console.WriteLine(sampleConfigSection.ToString());
	}
}

The configuration section will be generated automatically for the first time in HelloWorld.exe.xml as below.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <sample cinchoo:registryKey="HKLM\Software\sample" xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoDictionarySectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
</configuration>

Also the corresponding registry entries are created automatically if not exists as below

Please visit the CodeProject article below for more detailed information about this storage.

Cinchoo – Using Windows registry as configuration source

Cinchoo – Configuration framework, part 10

Inside Configuration Object Load Events

Download sample source files (Require .NET 4.0 / Visual Studio 2010)

In this section, I’ll go over the details of possible configuration object events you can define and their usage.

Load Events

Following are the events fired while loading  each Configuration object member values from underlying configuration source
  • BeforeConfigurationObjectMemberLoaded – Event fired before each configuration object member loaded.
  • AfterConfigurationObjectMemberLoaded – Event fired after each configuration object member loaded.
  • ConfigurationObjectMemberLoadError – Event fired when configuration object member had some error while loading.
Following are the events fired while loading  Configuration object from underlying configuration source
  • AfterConfigurationObjectLoaded – Event fired when configuration object loaded successfully.
  • ConfigurationObjectLoadError – Event fired when configuration object had some error while loading.

Order of events fired

Below diagram depicts the order of events fired while loading configuration parameters from the sources.

While loading each configuration member value from underlying source, framework fires BeforeConfigurationObjectMemberLoaded event when the configuration member value is different from underlying source value. In there you have chance to do validate, modify, massage the new value or do anything in here.

[ChoBeforeConfigurationObjectMemberLoadedHandler]
void OnBeforeConfigurationObjectMemberLoaded(object sender, ChoPreviewConfigurationObjectMemberEventArgs e)
{
}

Set ChoPreviewConfigurationObjectMemberEventArgs.Cancel to true/false, whether to continue the process of loading the value or not. Default is false.

If the value of ChoPreviewConfigurationObjectMemberEventArgs.Cancel is false, the framework will try to load the ChoPreviewConfigurationObjectMemberEventArgs.State (usually it carries the converted configuration member source value, which you have chance to inspect / modify it in this event handler) to the corresponding configuration object member. ChoPreviewConfigurationObjectMemberEventArgs.OriginalState contains the raw (unconverted) configuration member source value.  ChoPreviewConfigurationObjectMemberEventArgs.MemberName contains the configuration member name.

Then framework will fire AfterConfigurationObjectMemberLoaded event, where you have a chance to perform any post member related operations.

Above steps repeated for each member of the configuration object.

Any error will be captured and reported in the configuration log file. (Will talk about it later.)

Finally framework will fire AfterConfigurationObjectLoaded event after successful loading of configuration object. If for any reason finds any failure or exception during the loading operation, framework will fire ConfigurationObjectLoadError event, where you have chance to perform any recovery steps based on the error/exception.