Click here to Skip to main content
15,892,927 members
Articles / Programming Languages / C#

Zeta .NET Base Libraries

Rate me:
Please Sign up or sign in to vote.
4.41/5 (44 votes)
30 Mar 2007CPOL3 min read 151.9K   2.4K   147  
A small set of general-purpose classes for using in .NET applications
namespace ZetaLib.Core
{
	#region Using directives.
	// ----------------------------------------------------------------------

	using System;
	using System.Collections;
	using System.Collections.Specialized;
	using System.Configuration;
	using System.Globalization;
	using System.Diagnostics;
	using System.IO;
	using System.Net;
	using System.Threading;
	using System.Text;
	using System.Text.RegularExpressions;
	using System.Xml;
	using System.Net.Mail;
	using ZetaLib.Core.Base;
	using ZetaLib.Core.Common;
	using System.Reflection;
	using System.Collections.Generic;
	using ZetaLib.Core.Data;
	using ZetaLib.Core.Caching;
	using ZetaLib.Core.Logging;

	// ----------------------------------------------------------------------
	#endregion

	/////////////////////////////////////////////////////////////////////////

	/// <summary>
	/// Central class for managing all configuration aspects of the library.
	/// </summary>
	public class LibraryConfiguration :
		LibraryConfigurationBase,
		ILibraryConfiguration
	{
		#region Static routines.
		// ------------------------------------------------------------------

		/// <summary>
		/// Singleton access to the library configuratin.
		/// </summary>
		/// <value>The current.</value>
		public static LibraryConfiguration Current
		{
			get
			{
				if ( current == null )
				{
					// According to 
					// http://www.dofactory.com/Patterns/PatternSingleton.aspx,
					// it is sufficient to lock only the creation.
					// 
					// Quote:
					//		Support multithreaded applications through
					//		'Double checked locking' pattern which (once
					//		the instance exists) avoids locking each
					//		time the method is invoked 					
					//
					// http://geekswithblogs.net/akraus1/articles/90803.aspx
					// has the correct way of locking: declaring as "volatile".
					//
					// http://www.ibm.com/developerworks/java/library/j-dcl.html
					// has an in-deep discussion.
					lock ( typeLock )
					{
						if ( current == null )
						{
							// Please not that the following line does NOT return 
							// a fresh instance every time being called, but 
							// rather caches and return the same instance in 
							// subsequent calls.
							XmlNode section = ConfigurationManager.GetSection(
								@"zetaLibCore" ) as XmlNode;

							LibraryConfiguration result =
								new LibraryConfiguration();
							result.Initialize();
							result.LoadFromXml( section );

							current = result;
						}
					}
				}

				return current;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Public methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// Initialize this library.
		/// Please ensure to call this function once at the very start of your
		/// application, before doing any logging functions. A good place
		/// would be inside the Main() method or GLOBAL.ASAX file.
		/// </summary>
		public void Initialize()
		{
			if ( libraryInitialisator == null )
			{
				libraryInitialisator = new object();

				AdoNetCacheManager.Current.Initialize();
			}
		}

		/// <summary>
		/// Loads this class form the given configuration node.
		/// </summary>
		/// <param name="node">The node.</param>
		public void LoadFromXml(
			XmlNode node )
		{
			if ( node != null )
			{
				XmlHelper.ReadAttribute(
					out applicationRegistryKeyName,
					node.Attributes[@"applicationRegistryKeyName"] );
				XmlHelper.ReadAttribute(
					out administratorEMailAddress,
					node.Attributes[@"administratorEMailAddress"] );
				XmlHelper.ReadAttribute(
					out disableLoggingPasswordProtection,
					node.Attributes[@"disableLoggingPasswordProtection"],
					false );
				XmlHelper.ReadAttribute(
					out smtpServer,
					node.Attributes[@"smtpServer"] );
				XmlHelper.ReadAttribute(
					out smtpServerPort,
					node.Attributes[@"smtpServerPort"] );
				XmlHelper.ReadAttribute(
					out smtpServerUserName,
					node.Attributes[@"smtpServerUserName"] );
				XmlHelper.ReadAttribute(
					out smtpServerPassword,
					node.Attributes[@"smtpServerPassword"] );

				string s;
				XmlHelper.ReadAttribute(
					out s,
					node.Attributes[@"deletedFilesFolderPath"] );

				if ( !string.IsNullOrEmpty( s ) )
				{
					deletedFilesFolderPath = new DirectoryInfo( s );
				}

				// --

				XmlNode databaseNode =
					node.SelectSingleNode( @"database" );

				if ( databaseNode != null )
				{
					string connectionStringString = null;
					int commandTimeoutSeconds = 0;
					bool traceSqlEnabled = false;
					string cacheSqlBehaviorText = null;
					DatabaseConfiguration.DatabaseCacheSqlBehavior
						cacheSqlBehavior =
						DatabaseConfiguration.DatabaseCacheSqlBehavior.Partially;

					XmlHelper.ReadAttribute(
						out connectionStringString,
						databaseNode.Attributes[@"connectionString"] );
					XmlHelper.ReadAttribute(
						out commandTimeoutSeconds,
						databaseNode.Attributes[@"commandTimeoutSeconds"] );
					XmlHelper.ReadAttribute(
						out cacheSqlBehaviorText,
						databaseNode.Attributes[@"cacheSqlBehavior"] );

					if ( !string.IsNullOrEmpty( cacheSqlBehaviorText ) )
					{
						cacheSqlBehavior =
							(DatabaseConfiguration.DatabaseCacheSqlBehavior)
							Enum.Parse(
							typeof( DatabaseConfiguration.DatabaseCacheSqlBehavior ),
							cacheSqlBehaviorText,
							true );
					}

					XmlHelper.ReadAttribute(
						out traceSqlEnabled,
						databaseNode.Attributes[@"traceSqlEnabled"] );

					database = new DatabaseConfiguration(
						connectionStringString,
						commandTimeoutSeconds,
						cacheSqlBehavior,
						traceSqlEnabled );
				}

				// --

				XmlNode webNode =
					node.SelectSingleNode( @"web" );

				if ( webNode != null )
				{
					bool useServerSideViewState = false;
					string replaceTildeFallback = null;
					string replaceTildeCompleteFallback = null;
					bool useCustomErrors = false;

					XmlHelper.ReadAttribute(
						out useServerSideViewState,
						webNode.Attributes[@"useServerSideViewState"] );
					XmlHelper.ReadAttribute(
						out replaceTildeFallback,
						webNode.Attributes[@"replaceTildeFallback"] );
					XmlHelper.ReadAttribute(
						out replaceTildeCompleteFallback,
						webNode.Attributes[@"replaceTildeCompleteFallback"] );
					XmlHelper.ReadAttribute(
						out useCustomErrors,
						webNode.Attributes[@"useCustomErrors"] );

					web = new WebConfiguration(
						useServerSideViewState,
						replaceTildeFallback,
						replaceTildeCompleteFallback,
						useCustomErrors );
				}

				// --

				/*
				<webProxy
					address=""
					bypassProxyOnLocal="" >
					<credentials 
						domain=""
						userName=""
						password="" />
					<bypassList>
						<bypass rx="" />
						<bypass rx="" />
						<bypass rx="" />
						<bypass rx="" />
					</bypassList>
				</webProxy>
				*/

				XmlNode webProxyNode =
					node.SelectSingleNode( @"webProxy" );

				if ( webProxyNode != null )
				{
					bool hasEnabled = false;
					bool enabled = false;
					string address = null;
					bool hasBypassProxyOnLocal = false;
					bool bypassProxyOnLocal = false;

					hasEnabled =
						webProxyNode.Attributes[@"enabled"] != null;
					XmlHelper.ReadAttribute(
						out enabled,
						webProxyNode.Attributes[@"enabled"] );
					XmlHelper.ReadAttribute(
						out address,
						webProxyNode.Attributes[@"address"] );
					hasBypassProxyOnLocal =
						webProxyNode.Attributes[@"bypassProxyOnLocal"] != null;
					XmlHelper.ReadAttribute(
						out bypassProxyOnLocal,
						webProxyNode.Attributes[@"bypassProxyOnLocal"] );

					// If no address is given, ignore everything else.
					if ( hasEnabled && enabled &&
						!string.IsNullOrEmpty( address ) )
					{
						WebProxy webProxy = new WebProxy();
						webProxy.Address = new Uri( address );

						if ( hasBypassProxyOnLocal )
						{
							webProxy.BypassProxyOnLocal = bypassProxyOnLocal;
						}

						XmlNode credentialsNode =
							webProxyNode.SelectSingleNode( @"credentials" );

						if ( credentialsNode != null )
						{
							string domain = null;
							string userName = null;
							string password = null;

							XmlHelper.ReadAttribute(
								out domain,
								credentialsNode.Attributes[@"domain"] );
							XmlHelper.ReadAttribute(
								out userName,
								credentialsNode.Attributes[@"userName"] );
							XmlHelper.ReadAttribute(
								out password,
								credentialsNode.Attributes[@"password"] );

							// If no user name is given, ignore the credentials.
							if ( userName != null && userName.Length > 0 )
							{
								NetworkCredential credentials =
									new NetworkCredential();

								credentials.UserName = userName;
								credentials.Password = password;
								credentials.Domain = domain;

								webProxy.Credentials = credentials;
							}
						}

						XmlNodeList bypassNodes =
							webProxyNode.SelectNodes( @"bypassList/bypass" );

						if ( bypassNodes != null && bypassNodes.Count > 0 )
						{
							List<string> bypassRXs = new List<string>();

							foreach ( XmlNode bypassNode in bypassNodes )
							{
								string rx = null;

								XmlHelper.ReadAttribute(
									out rx,
									bypassNode.Attributes[@"rx"] );

								if ( rx != null && rx.Length > 0 )
								{
									bypassRXs.Add( rx );
								}
							}

							if ( bypassRXs.Count > 0 )
							{
								webProxy.BypassList = bypassRXs.ToArray();
							}
						}

						this.webProxy = webProxy;
					}
				}
			}
		}

		/// <summary>
		/// Central point to send an e-mail message.
		/// </summary>
		/// <param name="from">From.</param>
		/// <param name="to">To.</param>
		/// <param name="subject">The subject.</param>
		/// <param name="body">The body.</param>
		public void SendEMailMessage(
			string from,
			string to,
			string subject,
			string body )
		{
			MailMessage message = new MailMessage();

			message.IsBodyHtml = false;
			message.From = new MailAddress( from );
			message.Subject = subject;
			message.Body = body;
			message.To.Add( new MailAddress( to ) );

			SendEMailMessage( message );
		}

		/// <summary>
		/// Central point to send an e-mail message.
		/// </summary>
		/// <param name="message">The message.</param>
		public void SendEMailMessage(
			MailMessage message )
		{
			string smtpServer =
				ZetaLib.Core.LibraryConfiguration.Current.SmtpServer;

			try
			{
				LogCentral.Current.LogDebug(
					string.Format(
					@"Sending e-mail message. SMTP server: '{0}' (IP '{1}'), " +
					@"sender: '{2}', receiver: '{3}', subject: '{4}', body: '{5}'.",
					smtpServer,
					SafeResolveIPAddress( smtpServer ),
					message.From,
					message.To,
					message.Subject,
					message.Body ) );

				SmtpClient client;

				if ( ZetaLib.Core.LibraryConfiguration.Current.SmtpServerPort != 0 )
				{
					client = new SmtpClient(
						smtpServer,
						ZetaLib.Core.LibraryConfiguration.Current.SmtpServerPort );
				}
				else
				{
					client = new SmtpClient(
						smtpServer );
				}

				client.Send( message );
			}
			catch ( Exception x )
			{
				LogCentral.Current.LogError(
					string.Format(
					@"Error sending e-mail message. SMTP server: " +
					@"'{0}' (IP '{1}'), sender: '{2}', receiver: '{3}', " +
					@"subject: '{4}', body: '{5}'.",
					smtpServer,
					SafeResolveIPAddress( smtpServer ),
					message.From,
					message.To,
					message.Subject,
					message.Body ),
					x );

				throw;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Public properties.
		// ------------------------------------------------------------------

		/// <summary>
		/// Access the default cache manager.
		/// </summary>
		/// <value>The cache.</value>
		public CacheManager Cache
		{
			get
			{
				if ( cacheManager == null )
				{
					cacheManager = new CacheManager();
					cacheManager.Initialize();
				}

				return cacheManager;
			}
			set
			{
				cacheManager = value;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Configuration subclasses - database.
		// ------------------------------------------------------------------

		/// <summary>
		/// Configuration of the database.
		/// </summary>
		public class DatabaseConfiguration
		{
			#region Public enums.

			/// <summary>
			/// How caching of SQL statements is being handled.
			/// </summary>
			public enum DatabaseCacheSqlBehavior
			{
				#region Enum members.

				/// <summary>
				/// The cache is active, even if not explicitely requested
				/// by a caller.
				/// </summary>
				On,

				/// <summary>
				/// The cache is inactive, even if explicitely requested
				/// by a caller.
				/// </summary>
				Off,

				/// <summary>
				/// The cache is partially active, when being explicitely
				/// requested by a caller.
				/// </summary>
				Partially

				#endregion
			}

			#endregion

			#region Public methods.

			/// <summary>
			/// Constructor. Creates empty.
			/// </summary>
			public DatabaseConfiguration()
			{
				CheckGetDefaultConnectionString();
			}

			/// <summary>
			/// Constructor.
			/// </summary>
			/// <param name="connectionString">The connection string.</param>
			/// <param name="commandTimeoutSeconds">The command timeout seconds.</param>
			/// <param name="cacheSqlBehavior">The cache SQL behavior.</param>
			/// <param name="traceSqlEnabled">if set to <c>true</c> [trace SQL enabled].</param>
			public DatabaseConfiguration(
				string connectionString,
				int commandTimeoutSeconds,
				DatabaseCacheSqlBehavior cacheSqlBehavior,
				bool traceSqlEnabled )
			{
				this.connectionString = connectionString;
				this.commandTimeoutSeconds = commandTimeoutSeconds;
				this.cacheSqlBehavior = cacheSqlBehavior;
				this.traceSqlEnabled = traceSqlEnabled;

				CheckGetDefaultConnectionString();
			}

			#endregion

			#region Public properties.

			/// <summary>
			/// The connection string to the database.
			/// </summary>
			/// <value>The connection string.</value>
			public SmartConnectionString ConnectionString
			{
				get
				{
					return new SmartConnectionString( connectionString );
				}
			}

			/// <summary>
			/// The timeout for commands in seconds.
			/// </summary>
			/// <value>The command timeout seconds.</value>
			public int CommandTimeoutSeconds
			{
				get
				{
					return commandTimeoutSeconds;
				}
			}

			/// <summary>
			/// Whether SQL-statements and their results
			/// should be cached.
			/// </summary>
			/// <value>The cache SQL behavior.</value>
			public DatabaseCacheSqlBehavior CacheSqlBehavior
			{
				get
				{
					return cacheSqlBehavior;
				}
			}

			/// <summary>
			/// Whether SQL-statements should be traced.
			/// </summary>
			/// <value><c>true</c> if [trace SQL enabled]; otherwise, <c>false</c>.</value>
			public bool TraceSqlEnabled
			{
				get
				{
					return
						traceSqlEnabled &&
						LogCentral.Current.IsLoggingEnabled( LogType.Info );
				}
			}

			#endregion

			#region Private methods.

			/// <summary>
			/// Try to get a standard connection string if none
			/// is provided.
			/// </summary>
			private void CheckGetDefaultConnectionString()
			{
				if ( string.IsNullOrEmpty( connectionString ) )
				{
					// Entry 0 seems to be a default entry.
					if ( ConfigurationManager.ConnectionStrings.Count > 1 )
					{
						// Get the first one.
						connectionString =
							ConfigurationManager.ConnectionStrings[1].
							ConnectionString;
					}
				}
			}

			#endregion

			#region Private variables.

			private string connectionString = null;
			private int commandTimeoutSeconds = 0;
			private DatabaseCacheSqlBehavior cacheSqlBehavior =
				DatabaseCacheSqlBehavior.Partially;
			private bool traceSqlEnabled = false;

			#endregion
		}

		// ------------------------------------------------------------------
		#endregion

		#region Configuration subclasses - web.
		// ------------------------------------------------------------------

		/// <summary>
		/// Configuration of the web.
		/// </summary>
		public class WebConfiguration
		{
			#region Public methods.

			/// <summary>
			/// Constructor. Creates empty.
			/// </summary>
			public WebConfiguration()
			{
			}

			/// <summary>
			/// Constructor.
			/// </summary>
			/// <param name="useServerSideViewState">if set to <c>true</c> [use server side view state].</param>
			/// <param name="replaceTildeFallback">The replace tilde fallback.</param>
			/// <param name="replaceTildeCompleteFallback">The replace tilde complete fallback.</param>
			/// <param name="useCustomErrors">if set to <c>true</c> [use custom errors].</param>
			public WebConfiguration(
				bool useServerSideViewState,
				string replaceTildeFallback,
				string replaceTildeCompleteFallback,
				bool useCustomErrors )
			{
				this.useServerSideViewState = useServerSideViewState;
				this.replaceTildeFallback = replaceTildeFallback;
				this.replaceTildeCompleteFallback =
					replaceTildeCompleteFallback;
				this.useCustomErrors = useCustomErrors;
			}

			#endregion

			#region Public properties.

			/// <summary>
			/// Whether to use a server-side viewstate instead
			/// of a client-side viewstate.
			/// </summary>
			/// <value>
			/// 	<c>true</c> if [use server side view state]; otherwise, <c>false</c>.
			/// </value>
			public bool UseServerSideViewState
			{
				get
				{
					return useServerSideViewState;
				}
			}

			/// <summary>
			/// The string that is used when replacing a tilde
			/// and the result cannot be resolved.
			/// </summary>
			/// <value>The replace tilde fallback.</value>
			public string ReplaceTildeFallback
			{
				get
				{
					return replaceTildeFallback;
				}
			}

			/// <summary>
			/// The string that is used when replacing a tilde
			/// and the result cannot be resolved.
			/// </summary>
			/// <value>The replace tilde complete fallback.</value>
			public string ReplaceTildeCompleteFallback
			{
				get
				{
					return replaceTildeCompleteFallback;
				}
			}

			/// <summary>
			/// Whether to display custom errors on
			/// web pages.
			/// </summary>
			/// <value><c>true</c> if [use custom errors]; otherwise, <c>false</c>.</value>
			public bool UseCustomErrors
			{
				get
				{
					return useCustomErrors;
				}
			}

			#endregion

			#region Private variables.

			private bool useServerSideViewState = false;
			private bool useCustomErrors = false;
			private string replaceTildeFallback = null;
			private string replaceTildeCompleteFallback = null;

			#endregion
		}

		// ------------------------------------------------------------------
		#endregion

		#region Configuration properties.
		// ------------------------------------------------------------------

		/// <summary>
		/// The name of the application for storing values in the registry.
		/// Use the format "MyApplicationName".
		/// </summary>
		/// <value>The name of the application registry key.</value>
		public string ApplicationRegistryKeyName
		{
			get
			{
				if ( string.IsNullOrEmpty( applicationRegistryKeyName ) )
				{
					return Assembly.GetEntryAssembly().GetName().Name;
				}
				else
				{
					return applicationRegistryKeyName;
				}
			}
			set
			{
				applicationRegistryKeyName = value;
			}
		}

		/// <summary>
		/// The database configuration.
		/// </summary>
		/// <value>The database.</value>
		public DatabaseConfiguration Database
		{
			get
			{
				return database;
			}
		}

		/// <summary>
		/// The web configuration.
		/// </summary>
		/// <value>The web.</value>
		public WebConfiguration Web
		{
			get
			{
				return web;
			}
		}

		/// <summary>
		/// Configure to turn off protection of passwords
		/// stored inside the logfile.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if [disable logging password protection]; otherwise, <c>false</c>.
		/// </value>
		public bool DisableLoggingPasswordProtection
		{
			get
			{
				return disableLoggingPasswordProtection;
			}
		}

		/// <summary>
		/// The e-mail address of an administrator.
		/// Can be NULL.
		/// </summary>
		/// <value>The administrator E mail address.</value>
		public string AdministratorEMailAddress
		{
			get
			{
				if ( administratorEMailAddress == null ||
					administratorEMailAddress.IndexOf( ';' ) < 0 )
				{
					return administratorEMailAddress;
				}
				else
				{
					return administratorEMailAddress.Split( ';' )[0];
				}
			}
		}

		/// <summary>
		/// The e-mail address of an administrator.
		/// Can be NULL.
		/// </summary>
		/// <value>The administrator E mail addresses.</value>
		public string[] AdministratorEMailAddresses
		{
			get
			{
				if ( administratorEMailAddress == null )
				{
					return null;
				}
				else
				{
					if ( administratorEMailAddress.IndexOf( ';' ) < 0 )
					{
						return new string[] { administratorEMailAddress };
					}
					else
					{
						return administratorEMailAddress.Split( ';' );
					}
				}
			}
		}

		/// <summary>
		/// The server used to send e-mail messages via SMTP.
		/// Can be NULL.
		/// </summary>
		/// <value>The SMTP server.</value>
		public string SmtpServer
		{
			get
			{
				return smtpServer;
			}
			set
			{
				smtpServer = value;
			}
		}

		/// <summary>
		/// The server port used to send e-mail messages via SMTP.
		/// Is zero if not assigned.
		/// </summary>
		/// <value>The SMTP server port.</value>
		public int SmtpServerPort
		{
			get
			{
				return smtpServerPort;
			}
			set
			{
				smtpServerPort = value;
			}
		}

		/// <summary>
		/// The user name used to send e-mail messages via SMTP.
		/// Is null/empty if not assigned.
		/// </summary>
		/// <value>The name of the SMTP server user.</value>
		public string SmtpServerUserName
		{
			get
			{
				return smtpServerUserName;
			}
		}

		/// <summary>
		/// The user name used to send e-mail messages via SMTP.
		/// Is null/empty if not assigned.
		/// </summary>
		/// <value>The SMTP server password.</value>
		public string SmtpServerPassword
		{
			get
			{
				return smtpServerPassword;
			}
		}

		/// <summary>
		/// Get the web proxy settings. If no web proxy is configured
		/// in the configuration file, the default Internet Explorer
		/// proxy settings are returned.
		/// </summary>
		/// <value>The web proxy.</value>
		public IWebProxy WebProxy
		{
			get
			{
				if ( webProxy == null )
				{
					return WebRequest.DefaultWebProxy;
				}
				else
				{
					return webProxy;
				}
			}
		}

		/// <summary>
		/// For the "FileDeleteHelper" class.
		/// </summary>
		/// <value>The deleted files folder path.</value>
		public DirectoryInfo DeletedFilesFolderPath
		{
			get
			{
				return deletedFilesFolderPath;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// Helper.
		/// </summary>
		/// <param name="hostName">Name of the host.</param>
		/// <returns></returns>
		private string SafeResolveIPAddress(
			string hostName )
		{
			if ( hostName == null || hostName.Length <= 0 )
			{
				return string.Empty;
			}
			else
			{
				IPHostEntry entry =
					Dns.GetHostEntry( hostName );

				if ( entry == null ||
					entry.AddressList == null ||
					entry.AddressList.Length < 0 )
				{
					return string.Empty;
				}
				else
				{
					return entry.AddressList[0].ToString();
				}
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private variables.
		// ------------------------------------------------------------------

		private string applicationRegistryKeyName;
		private string administratorEMailAddress;
		private bool disableLoggingPasswordProtection;
		private string smtpServer;
		private int smtpServerPort;
		private string smtpServerUserName;
		private string smtpServerPassword;
		private DirectoryInfo deletedFilesFolderPath;
		private IWebProxy webProxy;

		private DatabaseConfiguration database =
			new DatabaseConfiguration();
		private WebConfiguration web =
			new WebConfiguration();

		/// <summary>
		/// Doing new initialization.
		/// </summary>
		private static object libraryInitialisator;

		/// <summary>
		/// 
		/// </summary>
		private static object typeLock = new object();

		/// <summary>
		/// The default cache manager.
		/// </summary>
		private CacheManager cacheManager;

		/// <summary>
		/// 
		/// </summary>
		private static volatile LibraryConfiguration current;

		// ------------------------------------------------------------------
		#endregion
	}

	/////////////////////////////////////////////////////////////////////////

	/// <summary>
	/// Read the configuration.
	/// See http://support.microsoft.com/?kbid=309045.
	/// </summary>
	internal sealed class LibraryConfigurationSectionHandler :
		IConfigurationSectionHandler
	{
		#region IConfigurationSectionHandler member.
		// ------------------------------------------------------------------

		/// <summary>
		/// Creates an instance of this class.
		/// </summary>
		/// <param name="parent">Parent object.</param>
		/// <param name="configContext">Configuration context object.</param>
		/// <param name="section">Section XML node.</param>
		/// <returns>The created section handler object.</returns>
		public object Create(
			object parent,
			object configContext,
			XmlNode section )
		{
			return section;
		}

		// ------------------------------------------------------------------
		#endregion
	}

	/////////////////////////////////////////////////////////////////////////
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Zeta Software GmbH
Germany Germany
Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He has also teached programming to students at the local university.

➡️ Give me a tip 🙂

In his free time, he does climbing, running and mountain biking. In 2012 he became a father of a cute boy and in 2014 of an awesome girl.

Some cool, free software from us:

Windows 10 Ereignisanzeige  
German Developer Community  
Free Test Management Software - Intuitive, competitive, Test Plans.  
Homepage erstellen - Intuitive, very easy to use.  
Offline-Homepage-Baukasten

Comments and Discussions