Tag Archives: Automatic

Cinchoo – Turn your app to Windows Tray app

In this article, I’ll show you how to turn your console / winform application to Windows System Tray application. Cinchoo framework provides a single hosting infrastructure to turn your application either Windows Service or Windows Tray application through configuration.

Console Application

Here is how you can do it for console application

1. Create a new ‘Console Application‘ from VS.NET

2. Add reference to Cinchoo.Core.dll

3. Add namespace Cinchoo.Core

4. Create a class derived from ChoApplicationHost as below

[RunInstaller(true)]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        //TODO: Application Startup code goes here
        base.OnStart(args);
    }
}

Decorating the above class with RunInstallerAttribute will make the application to be run as Windows Service. And override OnStart method, where application start up code placed there.

5. In the main entry, do as below.

public class Program
{
    static void Main(string[] args)
    {
        ChoApplication.Run(new AppHost(), args);
    }
}

That’s all, you application is now ready to run as self installable windows service application or Windows Tray application.

Here is how to turn your application to Windows Tray application. In ChoCoreFrx.xml file, set ‘turnOn’ flag to ‘true’ in trayApplicationBehaviourSettings element.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <globalApplicationSettings applicationId="TestApplication.exe" eventLogSourceName="TestApplication.exe" turnOnConsoleOutput="false">
    <behaviourSettings hideWindow="false" bringWindowToTop="false" alwaysOnTop="false" runAtStartup="false" runOnceAtStartup="false" singleInstanceApp="false" activateFirstInstance="false" />
    <trayApplicationBehaviourSettings turnOn="true" showInTaskbar="true" hideMainWindowAtStartup="true" hideTrayIconWhenMainWindowShown="false" trayAppTurnOnMode="OnMinimize" />
    <appConfigPath />
  </globalApplicationSettings>
</configuration>

Other parameters

  • showInTaskbar – true, will show the application in Taskbar. false, otherwise.
  • hideMainWindowAtStartup – true, will hide the window at the application startup. Otherwise false.
  • hideTrayIconWhenMainWindowShown – true, tray application icon will hidden when the main windows shown. Otherwise false.
  • trayAppTurnOnMode – This option is applicable to WinForm application only. Possible options are OnMinimize, OnClose, OnMinimizeOrClose.

WinForm Application

Below are the steps to turn your winform application into Windows Tray application

1. Create a new ‘WinForm Application‘ from VS.NET

2. Add reference to Cinchoo.Core.dll

3. Add namespace Cinchoo.Core

4. Create a class derived from ChoApplicationHost and IChoWinFormApp as below

[RunInstaller(true)]
public class AppHost : ChoApplicationHost, IChoWinFormApp
{
    MainForm form = new MainForm();
    public AppHost()
    {
    }

    public Form MainFormWindow
    {
        get { return form; }
    }

    public ContextMenu GetContextMenu(ContextMenu contextMenu)
    {
        //Build the context menu items
        return contextMenu;
    }

    public string TooltipText
    {
        get { return null; }
    }

    public System.Drawing.Icon TrayIcon
    {
        get { return null; }
    }

    public string BalloonTipText
    {
        get { return null; }
    }

    protected override void OnStart(string[] args)
    {
        base.OnStart(args);
    }
}

Decorating the above class with RunInstallerAttribute will make the application to be run as Windows Service. And override OnStart method, where application start up code placed there.

5. In the main entry, do as below.

public class Program
{
    static void Main(string[] args)
    {
        ChoApplication.Run(new AppHost(), args);
    }
}

Thats all. Try it.


Cinchoo – Windows Service made easy

Cinchoo framework simplifies the Windows service development. An application developed in this approach is ready to run as Console application as well as self install-able Service application. In this article, I’m going to walk over the steps of creating service development.

1. Create a new ‘Console Application‘ from VS.NET

2. Add reference to Cinchoo.Core.dll

3. Add namespace Cinchoo.Core

4. Create a class derived from ChoApplicationHost as below

[RunInstaller(true)]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        //TODO: Application Startup code goes here
    }
}

Make sure the type is decorated with RunInstallerAttribute. And override OnStart method, where application start up code placed there. Implement any other service related (OnStop, OnShutdown etc) methods by overriding them.

5. In the main entry, do as below.

public class Program
{
    static void Main(string[] args)
    {
        ChoApplication.Run(new AppHost(), args);
    }
}

That’s all, you application is self install ready windows service application.

You can run it as console application or install it as Windows service also.

To Install as windows service, pass /i command line argument

[AppExeName].exe /i

To uninstall as windows service, pass /u command line argument

[AppExeName].exe /u

To start the service, pass /s command line argument

[AppExeName].exe /s

To stop the service, pass /t command line argument

[AppExeName].exe /t

To pause the service, pass /p command line argument

[AppExeName].exe /p

To continue the service, pass /c command line argument

[AppExeName].exe /c

To execute a command in the service, pass /e:{command_id} command line argument

[AppExeName].exe /e:2

Controlling Service Installation

There are couple of settings classes which controls the service process behavior during installation. It can configured through configuration file or can be overridden programmatically. They are

  • ChoServiceInstallerSettings – service process parameters used during installation of service.
  • ChoServiceProcessInstallerSettings – service credential parameters used during installation of the service.

First, let take a look at the way configuring them through configuration file.

ChoServiceProcessInstallerSettings

These setting can be maintained in ChoServiceProcessInstallerSettings.xml file. If the file not exists, it will created by Cinchoo framework in application configuration directory. The file look as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceProcessInstallerSettings account="LocalSystem" userName="" password="">
    <helpText />
  </serviceProcessInstallerSettings>
</configuration>

If you want more information about each attribute/element in the above xml section, please visit ServiceProcessInstaller Class in MSDN.

ChoServiceInstallerSettings

These setting can be maintained in ChoServiceInstallerSettings.xml file. If the file not exists, it will created by Cinchoo framework in application configuration directory. The file look as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings delayedAutoStart="false" displayName="ChoServiceHost.Test" serviceName="ChoServiceHost.Test" serviceStartMode="Automatic" />
</configuration>

If you want more information about each attribute/element in the above xml section, please visit ServiceInstaller Class in MSDN.

Next, let take a look at the way of overriding them programmatically.

Override ApplyServiceInstallParamsOverrides method in your ApplicationHost class, where you can changes service installation parameters.

[RunInstaller(true)]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("Application started...");
    }

    protected override void ApplyServiceInstallParamsOverrides(ChoServiceProcessInstallerSettings serviceProcessInstallerSettings, ChoServiceInstallerSettings serviceInstallerSettings)
    {
        serviceInstallerSettings.DisplayName = "Test";
        serviceInstallerSettings.ServiceName = "Test";
    }
}

In the above sample code, we are trying to override the ServiceName and DisplayName as ‘Test’. When you install the service, it will be created as ‘Test’ service.


Cinchoo – Framework Tips

Here I’m going to talk about couple of tips on using Cinchoo framework in your project.

At the start of the application, you must call ChoFramework.Initialize() to initialize the framework and start necessary services. Usually you must place this statement in application Main entry point as below.

Calling ChoFramework.Shutdown() method is not mandatory to call. But it is safe to make this call for graceful shutdown of all the background services.

static void Main(string[] args)
{
    ChoFramework.Initialize();
    try
    {
        ChoApplication.ApplyFrxParamsOverrides += new EventHandler<ChoFrxParamsEventArgs>(ChoApplication_ApplyFrxParamsOverrides);

        SampleConfigSection ApplicationSettings = new SampleConfigSection();
    }
    catch (Exception ex)
    {
        Console.WriteLine("ERROR: " + ex.Message);
    }
    finally
    {
        ChoFramework.Shutdown();
    }
}

ChoAppDomain.


Cinchoo – Overriding Framework Configuration Parameters

In this section, I’ll go over the list of Cinchoo framework configuration parameters can be overridden to control the run-time environment of the framework either through configuration or programmatically.

Framework will run fine without overriding these parameters. Only when you need, you can override them. In those situation, it can be done through configuration or programmatically.

First, we will see how to override them through configuration. All the framework parameters must be stored in ChoCoreFrx.config file under application executable folder. This is the default behavior of discovering this file by the framework. But this can be overridden by specifying the path to this file through appFrxSettings custom configuration section in App.config file as below

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

GlobalApplicationSettings

There are the application level settings used by framework. Below are the attributes and their usages.

  • globalApplicationSettings – Global application parameters used by framework. All the variables are optional.
    • singleInstanceApp [bool] – true, to ensure there is only one instance of the application running at any point in time. false, lets you to run multiple instances of the application. Default is false.
    • applicationId [string] – the custom application name. Default value is the executable name.
    • eventLogSourceName [string] – Event log source name where all the errors are posted on this name, default value is applicationId.
    • useApplicationDataFolderAsLogFolder [bool] – true, it uses the current roaming user directory. Default is false.
    • logFolder [string] – A log directory, where all the log files are created by framework. Default is ‘[appExePath]\Logs’.
    • appConfigPath [string] – configuration file path. If not specified, this will be [appExeFolder].[appExeName].xml
    • logTimeStampFormat [string] – A time stamp format used when logging information to log files. Default value is “yyyy-MM-dd hh:mm:ss.fffffff”
    • traceLevel [int] – Specifies what message to output for the Trace/ChoTrace classes. 0-Off, 1-Error, 2-Warning, 3-Info, 4-Verbose.

Here is the sample Global Application Settings section in ChoCoreFrx.config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <globalApplicationSettings singleInstanceApp="false" applicationId="TestApplication" eventLogSourceName="TestApplication" useApplicationDataFolderAsLogFolder="false">
    <logFolder>C:\Logs</logFolder>
    <appConfigPath>c:\config\TestApplication.xml</appConfigPath>
    <logTimeStampFormat>yyyy-MM-dd hh:mm:ss.fffffff</logTimeStampFormat>
  </globalApplicationSettings>
</configuration>

MetaDataFilePathSettings

Cinchoo framework creates as well as uses number of Meta-Data files, these file paths can be configured through ChoCoreFrx.config file.

  • configurationMetaDataFilePath – meta data file path used by Configuration manager. By default, it’s value is [appExeName].config.meta
  • pcMetaDataFilePath – meta data file path used by Performance Counter manager. By default, its value is [appExeName].perf.meta

Here is the sample xml section looks like

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <metaDataFilePathSettings>
    <configurationMetaDataFilePath>c:\Config\configurationMetaFile.meta</configurationMetaDataFilePath>
    <pcMetaDataFilePath>c:\Config\PCMetaFile.meta</pcMetaDataFilePath>
  </metaDataFilePathSettings>
</configuration>

Run-Time approach

Lets see how we can override the system parameters at run-time in here. Cinchoo framework exposes ChoApplication.ApplyFrxParamsOverrides event. By subscribing to this event, you have a chance to override the framework parameters at run-time. See below the sample code on how to override some of the system parameters

static void Main(string[] args)
{
    try
    {
        ChoApplication.ApplyFrxParamsOverrides += new EventHandler<ChoFrxParamsEventArgs>(ChoApplication_ApplyFrxParamsOverrides);
        XmlApplicationSettings ApplicationSettings = new XmlApplicationSettings();
    }
    finally
    {
        ChoAppDomain.Exit();
    }
}

static void ChoApplication_ApplyFrxParamsOverrides(object sender, ChoFrxParamsEventArgs e)
{
    e.GlobalApplicationSettings.SingleInstanceApp = true;
    e.MetaDataFilePathSettings.ConfigurationMetaDataFilePath = @"C:\Config\MetaDataFilePath.meta";
}

Cinchoo – Binary Downloads

Developers, please bookmark this page. I’ll keep updating the state of the framework in this post.

Jul 21, 2014 / v1.0.4.5 (Latest)

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • ENCH: Special handling of bool type in Command Line argument parser.

Jul 20, 2014 / v1.0.4.4

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • BUG FIX: Bug fixes on Command Line argument parser.

Jul 16, 2014 / v1.0.4.3 

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • BUG FIX: Bug fixes on Command Line argument parser.

Jul 09, 2014 / v1.0.4.2

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • BUG FIX: Minor bug fixes.

Jun 30, 2014 / v1.0.4.1

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • BUG FIX: User reported issue with Configuration Xml file creation.

Mar 09, 2014 / v1.0.4.0

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • BUG FIX: Issue setting configuration folder programatically.
static void ChoApplication_ApplyFrxParamsOverrides(object sender, ChoFrxParamsEventArgs e)
{
   e.AppFrxSettings.AppFrxFilePath = @"C:\Config";
}

Mar 09, 2014 / v1.0.3.9

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • Fixed race condition in creating and managing individual Configuration Section files.

Feb 13, 2014 / v1.0.3.8

Cinchoo.Framework.Dlls.Zip (Any CPU)

  • Fixed the issue related to turning on/off Framework logging completely using ChoSwitch (System.Diagnostics.Switch). in App.Config as below. Possible switch are Off, Verbose, Info, Warning, Error.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<system.diagnostics>
		<switches>
			<add name="ChoSwitch" value="Off" />
		</switches>
	</system.diagnostics>
</configuration>

Please post your valuable feedback in this blog. Also if I miss anything, please email me at cinchoofrx@gmail.com. Glad to add them in future releases. Thanks for your support.


Cinchoo – Using Performance Counters, Part 1

In this section I’ll discusses about how we can use Cinchoo framework’s performance counter helper class to gather data from an application. So we will first understand the fundamentals and then we will see a simple example from which we will collect some performance data.

Before we begin, if you like to know more information about Performance Counter, please visit below links

MSDN Performance Counter Class

An Article on Performance Counter in CodeProject

Cinchoo framework provides nifty performance counter helper classes to makes it easier for developers to develop applications that use Performance Counter to monitor the health of the application.

There are two types of Performance Counter Categories

  • SingleInstance - The performance counter category can have only a single instance.
  • MultipleInstance - The performance counter category can have multiple instances.

Creating and using SingleInstance Performance Counters

1. Add reference to Cinchoo.Core.dll assembly

2. Namespace Cinchoo.Core.Instrumentation.Performance

[ChoPerformanceCounterCategory("Random Single Instance Test", PerformanceCounterCategoryType.SingleInstance)]
public sealed class SingleInstancePerfCounters : ChoPerformanceCounterCategory
{
    #region Performance Counters

    [ChoPerformanceCounter("Random Rate", "", PerformanceCounterType.RateOfCountsPerSecond32)]
    public readonly ChoPerformanceCounter PCRandomRate = null;

    [ChoPerformanceCounter("Random Average", "", PerformanceCounterType.AverageCount64)]
    public readonly ChoPerformanceCounter PCRandomAverage = null;

    #endregion
}
 Now lets see how to instantiate and use them
[STAThread]
static void Main(string[] args)
{
    SingleInstancePerfCounters perfCounter = new SingleInstancePerfCounters();

    Random rand = new Random(42);
    int randMax = 100;

    while (true)
    {
        int r = rand.Next(randMax);

        if (perfCounter.PCRandomRate != null)
            perfCounter.PCRandomRate.Increment();
        if (perfCounter.PCRandomAverage != null)
            perfCounter.PCRandomAverage.IncrementBy(r);

        Thread.Sleep(1000);
    }
}

Creating and using MultipleInstance Performance Counters

1. Add reference to Cinchoo.Core.dll assembly

2. Namespace Cinchoo.Core.Instrumentation.Performance

[ChoPerformanceCounterCategory("Random Multiple Instance Test", PerformanceCounterCategoryType.MultiInstance)]
public sealed class MultipleInstancePerfCounters : ChoPerformanceCounterCategory
{
    #region Performance Counters

    [ChoPerformanceCounter("Random Value", "", PerformanceCounterType.NumberOfItems64, "Standard")]
    public readonly ChoPerformanceCounter PCRandomValue;

    [ChoPerformanceCounter("Random Value", "", PerformanceCounterType.NumberOfItems64, "Inverted")]
    public readonly ChoPerformanceCounter PCRandomInvertedValue;

    #endregion
}

Please remember that the above two Performance counter members are given same category name ‘Random Value’ and different instance names. It qualifies them to create multiple instances of performance counters.

Now lets see how to instantiate and use them

[STAThread]
static void Main(string[] args)
{
    MultipleInstancePerfCounters perfCounter = new MultipleInstancePerfCounters();

    Random rand = new Random(42);
    int randMax = 100;

    while (true)
    {
        int r = rand.Next(randMax);

        if (perfCounter.PCRandomValue != null)
            perfCounter.PCRandomValue.RawValue = r;
        if (perfCounter.PCRandomInvertedValue != null)
            perfCounter.PCRandomInvertedValue.RawValue = randMax - r;

        Thread.Sleep(1000);
    }
}

In the next part, will see how to control the Performance Counters through configuration.


Cinchoo – Configuration framework, part 14

Configuration Objects Logs

Cinchoo framework creates a  log file for each configuration object separately. Those log files are created under application binary folder. By default the log file name are generated from configuration object type full name.

For a sample configuration object below

namespace HelloWorld
{
	#region NameSpaces

	using System;
	using Cinchoo.Core.Configuration;

	#endregion NameSpaces

	[ChoConfigurationSection("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
	}
}

The log file will be created in the name of HelloWorld.SampleConfigSection.log under Application Bin/Settings folder.

2012-03-19 05:18:47.7648110
  -- HelloWorld.SampleConfigSection State --
	Name: Mark
	Message: Hello World!

-- MetaData Information --
	BindingMode: TwoWay
	Defaultable: True
	IgnoreError: True
	ConfigurationMetaDataLogInfo:
		-- Log Information --
			Condition: True
			TimeStampFormat:
			TraceOutputDirectory: Settings
			TraceOutputFileName: HelloWorld.SampleConfigSection.log

	ConfigStorageType: Cinchoo.Core.Configuration.Storage.ChoFileNameValueConfigStorage, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de

Application Log Folder can be overridden in both ways

  • Globally at the application level
  • Locally at each configuration object level

1. Overriding Global Log Folder

The application log folder can be overridden. Please visit Framework Configuration Parameters section on how to do it.

2. Overriding at individual configuration at object level

In some cases, you may want to redirect the log files of individual configuration object to some specific folder. In that moment, it can achieved as below.

namespace HelloWorld
{
	#region NameSpaces

	using System;
	using Cinchoo.Core.Configuration;

	#endregion NameSpaces

	[ChoConfigurationSection("sample", TraceOutputDirectory = @"C:\CustomLogsFolder")]
	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
	}
}

In this sample, we can route the log files of Configuration Object to C:/CustomLogsFolder directory using TraceOutputDirectory attribute member as below.

You can even override the individual configuration object log file through TraceOutputFileName attribute member as below

namespace HelloWorld
{
	#region NameSpaces

	using System;
	using Cinchoo.Core.Configuration;

	#endregion NameSpaces

	[ChoConfigurationSection("sample", TraceOutputDirectory = @"C:\CustomLogsFolder", TraceOutputFileName = "OverriddenSampleConfigObject.log")]
	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
	}
}

Cinchoo – Configuration framework, part 13

Managing Large Configuration file

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

Suppose in a large application built on several components packaged in their own assemblies, managing configuration file in one file will be tedious. Using Cinchoo configuration framework, you can split them into manageable small files. I’ll walk you over the steps to split them and use them in a application.

There are couple of ways, you can achieve the splitting of configuration files

1. Automatic Split (Code first approach)

This approach is viable in case of new development where there are no existing configuration files available.  In this scenario, you just design and implement the configuration objects first and let the Cinchoo framework generate the configuration files for you. I’ll walk you over on how to do it using this approach.

You can specify the individual configuration file for each configuration object using ChoConfigurationSectionAttribute, where you must give the name of the configuration file in one of the property

  • ConfigFilePath - Configuration file path in string either full path or just file name.
  • ConfigFilePathFromTypeName – For a given type specified to this property, it takes the name of the type as configuration file name.
  • ConfigFilePathFromTypeFullName - For a given type specified to this property, it takes the fully qualified namespace name of the type as configuration file name.

For a sample console application named SplitConfigUsingCodeFirstApproach.exe, defining the below two configuration objects

[ChoNameValueConfigurationSection("serverDetails/environments", ConfigFilePathFromTypeName = typeof(ServerEnvironments))]
public class ServerEnvironments : ChoConfigurableObject
{
    public string Host = "WNYC1000234011";
    public string IP = "205.12.5.122";
    public int Port = 2001;
}

[ChoNameValueConfigurationSection("applicationSettings", ConfigFilePath = "ApplicationSettings" )]
public class ApplicationSettings : ChoConfigurableObject
{
    public string Mode = "LIVE";
    public bool IsConnected = true;
    public string Exchange = "NYSE";
}

Just instantiate the above objects in the Main entry method as below, Cinchoo framework creates the configuration files automatically.

class Program
{
    static void Main(string[] args)
    {
        ServerEnvironments serverEnvironments = new ServerEnvironments();
        ApplicationSettings applicationSettings = new ApplicationSettings();

        ChoFramework.Shutdown();
    }
}

The main application configuration file (SplitConfigUsingCodeFirstApproach.exe.xml)  is generated as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <applicationSettings cinchoo:path="C:\CinchooConfigurationFrxDemos\SplitConfigUsingCodeFirstApproach\SplitConfigUsingCodeFirstApproach\bin\Debug\ApplicationSettings.xml" xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
  <serverDetails>
    <environments cinchoo:path="C:\CinchooConfigurationFrxDemos\SplitConfigUsingCodeFirstApproach\SplitConfigUsingCodeFirstApproach\bin\Debug\ServerEnvironments.xml" xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
  </serverDetails>
</configuration>

And the splitted configuration files corresponding to two configuration objects defined in the code are generated automatically by the framework.

For the ServerEnvironments object, the file named ServerEnvironments.xml is generated as below

<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <sectionGroup name="serverDetails">
      <section name="environments" type="Cinchoo.Core.Configuration.Handlers.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
    </sectionGroup>
  </configSections>
  <serverDetails>
    <environments>
      <add key="Host" value="WNYC1000234011" />
      <add key="IP" value="205.12.5.122" />
      <add key="Port" value="2001" />
    </environments>
  </serverDetails>
</configuration>

For the ApplicationSettings object, the file named ApplicationSettings.xml is generated as below

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="applicationSettings" type="Cinchoo.Core.Configuration.Handlers.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
  <applicationSettings>
    <add key="Mode" value="LIVE" />
    <add key="IsConnected" value="True" />
    <add key="Exchange" value="NYSE" />
  </applicationSettings>
</configuration>

For any reason, the configuration files needs to be re-created, all you have to do is delete the configuration files or removing the configuration sections from the configuration file will trigger the Cinchoo framework to regenerate them seamlessly.

2. Manual Step (Configuration model first approach)

This approach is suitable if you already have established configuration file, you can use this method to split them.

Lets say, you have application configuration file named HelloWorld.exe.xml 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="serverDetails" type="Cinchoo.Core.Configuration.Handlers.ChoNameValueSectionHandler, Cinchoo.Core" />
        <sectionGroup name="allSections">
            <section name="sample" type="Cinchoo.Core.Configuration.Handlers.ChoXmlSerializerSectionHandler, Cinchoo.Core" />
        </sectionGroup>
    </configSections>
    <serverDetails Name="Mark">
        <Message>Hello World!</Message>
    </serverDetails>
    <allSections>
        <sample Name="Mark">
            <Message>Hello World!</Message>
        </sample>
    </allSections>
</configuration>

Above configuration file contains two sections ‘serverDetails’ and ‘allSections/sample’. I’m going to split this file into two files and show you how to link them together in the main configuration file.

The main configuration file HelloWorld.exe.xml will look as below after the split

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <serverDetails cinchoo:path="ServerDetails.xml" xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
    <allSections>
        <sample cinchoo:path="Sample.xml" xmlns:cinchoo="http://schemas.cinchoo.com/cinchoo/01/framework" />
    </allSections>
</configuration>

The splitted configuration files ServerDetails.xml and Sample.xml files will look below

ServerDetails.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="serverDetails" type="Cinchoo.Core.Configuration.Handlers.ChoXmlSerializerSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
    </configSections>
    <serverDetails Name="Mark">
        <Message>Hello World!</Message>
    </serverDetails>
</configuration>

Sample.xml

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <sectionGroup name="allSections">
            <section name="sample" type="Cinchoo.Core.Configuration.Handlers.ChoXmlSerializerSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
        </sectionGroup>
    </configSections>
    <allSections>
        <sample Name="Mark">
            <Message>Hello World!</Message>
        </sample>
    </allSections>
</configuration>

Cinchoo – Configuration framework, part 12

Using ChoFileXmlSerializerConfigStorage

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

In this section, I’ll go over the details of using ChoFileXmlSerializerConfigStorage in your application. It’s a custom configuration section handler enables application to read and write application settings from configuration file in complex Xml format.

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

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

    [XmlAttribute]
    public string Name;

    [XmlElement]
    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>
  <sample Name="Mark">
    <Message>Hello World!</Message>
  </sample>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoXmlSerializerSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
</configuration>

Cinchoo – ChoObject.ToString(), Part 10

Defining and using TypeConverter

Sometime you may want to customize the object member string represent. One way of achieving it by creating TypeConverter or existing .NET type converters and using them.

Defining TypeConverter

 Please visit MSDN on How to: Implement a Type Converter. Below is the sample converter
public class ChoArrayToStringConverter : TypeConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(string))
            return true;
        else
            return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (value == null)
            return null;

        StringBuilder msg = new StringBuilder();
        if (value.GetType().IsArray)
        {
            foreach (object item in (Array)value)
            {
                if (msg.Length == 0)
                    msg.Append(ChoString.ToString(item, String.Empty, String.Empty));
                else
                    msg.AppendFormat(", {0}", ChoString.ToString(item, String.Empty, String.Empty));
            }
            return msg.ToString();
        }
        return base.ConvertFrom(context, culture, value);
    }
}

Please visit .NET TypeConverters for the list of Type Converters that .NET provides. Those can be used in here in converting members to string represent.

Using TypeConverter

[ChoTypeFormatter("'{this.Name}' Security State")]
public class Portfolio : ChoObject
{
    public string Name;
    public string Description;
    [ChoMemberFormatter(TypeConverter = typeof(ChoArrayToStringConverter))]
    public string[] Securities;
    [ChoMemberFormatter(TypeConverter = typeof(BooleanConverter))]
    public bool Live;

    public Portfolio(string name, string description, string[] securities)
    {
        Name = name;
        Description = description;
        Securities = securities;
    }
}

static void Main(string[] args)
{
    try
    {
        Portfolio portfolio = new Portfolio("High-Growth", "High Growth Portfolio", new string[] { "AAPL", "GOOG", "IBM" });
        Console.WriteLine(portfolio.ToString());
    }
    finally
    {
        ChoAppDomain.Exit();
    }
}

The output will be

-- 'High-Growth' Security State --
        Name: High-Growth
        Description: High Growth Portfolio
        Securities: AAPL, GOOG, IBM
        Live: False

Press any key to continue . . .

Happy coding!!!


Follow

Get every new post delivered to your Inbox.