Specify multiple config file in enterpriseLibrary.ConfigurationSource

Topics: Enterprise Library Core
Oct 27, 2014 at 4:36 PM
Let me give some background to our requirement. We have a in house built application say App1 and Microsoft ESB tool kit both sing enterprise Library (5.0.414.0).
Both these component worked perfectly fine independently using the EL configuration. The configuration file to be used in either case would be like this.

<enterpriseLibrary.ConfigurationSource selectedSource="MWS File Configuration Source2" >
<sources>
  <add name="MWS File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35" filePath="E:\tools\EntLib\ConsoleApplication10\ABC.EntLib.config" />
  <add name="MWS File Configuration Source2" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=5.0.414.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35" filePath="E:\tools\EntLib\ConsoleApplication10\ABC.EntLib2.config" />
</sources>
</enterpriseLibrary.ConfigurationSource>

When we try to get both the components to work together it doesn't work. That's because the selected source takes only one file. If we consolidate the two config files into one then it works but unfortunately it will make manageability difficult as people would not expect configuration from in-house component into a MS product config file and vice-versa. We have also tried the parentSource attribute but couldn't get it to work. It still requires the entries to be made in the selectedSource file. Please help! The aim is to keep the config of two different components using EL separate.
Oct 29, 2014 at 12:29 AM
You can use the merge configuration source approach outlined in this posting: http://entlib.codeplex.com/discussions/253733 .

Use the MergeConfigurationSource code posted (clean up so it compiles (e.g. missing exception) and make any other mods you want). Then you can just use it to configure Enterprise Library at application startup:
var myAppConfigBuilder = new ConfigurationSourceBuilder();
var myAppConfigurationSource = new FileConfigurationSource("myapp.config");
myAppConfigBuilder.UpdateConfigurationWithReplace(myAppConfigurationSource);

var esbConfigBuilder = new ConfigurationSourceBuilder();
var esbConfigurationSource = new FileConfigurationSource("esb.config");
esbConfigBuilder.UpdateConfigurationWithReplace(esbConfigurationSource);

var mergeConfigurationSource = new MergeConfigurationSource(myAppConfigurationSource, esbConfigurationSource);

EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(mergeConfigurationSource); 

// MyApp category defined in MyApp.config
Logger.Write("MyApp message", "MyApp");

// ESB category defined in ESB.config
Logger.Write("ESB message", "ESB");

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Marked as answer by sajidalibaig on 11/6/2014 at 3:57 AM
Oct 30, 2014 at 3:59 PM
Hi Randy, Thanks for the response. I wanted to try this out however I don’t find this class or any reference in code,
MergeConfigurationSource mergConfigurationSource = new MergeConfigurationSource(myAppConfigurationSource, esbConfigurationSource);

Could you please help me locate the class?
If I could do this merging in my custom application and just leave the ESB as it this that would solve my problem.
Oct 30, 2014 at 4:31 PM
The MergeConfigurationSource code was in the post that I referenced.

Here's a slightly modified version of that code:
    /// <summary>
    /// Takes two <see cref="IConfigurationSource"/>s and tries to merge settings from both
    /// </summary>
    public class MergeConfigurationSource : IConfigurationSource
    {
        #region Fields

        private readonly HierarchicalConfigurationSourceHandler hierarchicalConfigurationSourceHandler;
        private readonly CompositeConfigurationSourceHandler compositeConfigurationSourceHandler;
        private readonly IConfigurationSource parentSource;
        private readonly IConfigurationSource localSource;

        private readonly object eventHandlersLock;  // lock used to protect the event handlers list
        private readonly EventHandlerList eventHandlers;

        #endregion Fields

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="MergeConfigurationSource"/> class.
        /// </summary>
        /// <param name="localSource">The local source.</param>
        /// <param name="parentSource">The parent source.</param>
        /// <remarks>Naming of the parameters uses Enterprise Library conventions 
        /// (<seealso cref="hierarchicalConfigurationSourceHandler"/>)</remarks>
        public MergeConfigurationSource(IConfigurationSource localSource, IConfigurationSource parentSource)
        {
            if (localSource == null) throw new ArgumentNullException("localSource");
            if (parentSource == null) throw new ArgumentNullException("parentSource");

            this.localSource = localSource;
            this.parentSource = parentSource;

            this.localSource.SourceChanged += OnSourceChanged;
            this.parentSource.SourceChanged += OnSourceChanged;

            hierarchicalConfigurationSourceHandler = new HierarchicalConfigurationSourceHandler(this.localSource, this.parentSource);
            compositeConfigurationSourceHandler = new CompositeConfigurationSourceHandler(this.parentSource);

            eventHandlersLock = new object();
            eventHandlers = new EventHandlerList();
        }

        #endregion Constructor

        /// <inheritdoc/>
        public event EventHandler<ConfigurationSourceChangedEventArgs> SourceChanged = delegate { };

        /// <inheritdoc/>
        public void Dispose()
        {
            hierarchicalConfigurationSourceHandler.Dispose();
            compositeConfigurationSourceHandler.Dispose();

            parentSource.Dispose();
            localSource.Dispose();
        }

        /// <summary>
        /// Gets a section identified by its <paramref name="sectionName"/>. If the section exists in local and parent source it
        /// will be merged.
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <returns>The configuration section with the given <paramref name="sectionName"/>; <c>null</c> if no such section can be found.</returns>
        public ConfigurationSection GetSection(string sectionName)
        {
            if (sectionName == null) throw new ArgumentNullException("sectionName");

            ConfigurationSection configurationSection = localSource.GetSection(sectionName);

            configurationSection = compositeConfigurationSourceHandler.CheckGetSection(sectionName, configurationSection);

            return hierarchicalConfigurationSourceHandler.CheckGetSection(sectionName, configurationSection);
        }

        /// <summary>
        /// Adds the specified section to the local configuration source
        /// </summary>
        /// <param name="sectionName">Name of the section.</param>
        /// <param name="configurationSection">The configuration section.</param>
        public void Add(string sectionName, ConfigurationSection configurationSection)
        {
            if (sectionName == null) throw new ArgumentNullException("sectionName");
            if (configurationSection == null) throw new ArgumentNullException("configurationSection");

            if (!compositeConfigurationSourceHandler.CheckAddSection(sectionName, configurationSection))
            {
                try
                {
                    localSource.Add(sectionName, configurationSection);
                }
                catch (Exception innerException)
                {
                    var exception = new Exception("Failed to add section: " + sectionName, innerException);

                    throw exception;
                }
            }
        }

        /// <summary>
        /// Removes the specified section from parent and local configuration source
        /// </summary>
        /// <param name="sectionName">Name of the section to remove</param>
        public void Remove(string sectionName)
        {
            if (sectionName == null) throw new ArgumentNullException("sectionName");

            if (!compositeConfigurationSourceHandler.CheckRemoveSection(sectionName))
            {
                localSource.Remove(sectionName);
                parentSource.Remove(sectionName);
            }
        }

        /// <inheritdoc/>
        public void AddSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler)
        {
            if (sectionName == null) throw new ArgumentNullException("sectionName");
            if (handler == null) throw new ArgumentNullException("handler");

            lock (eventHandlersLock)
            {
                eventHandlers.AddHandler(sectionName, handler);
            }
        }

        /// <inheritdoc/>
        public void RemoveSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler)
        {
            if (sectionName == null) throw new ArgumentNullException("sectionName");
            if (handler == null) throw new ArgumentNullException("handler");

            lock (eventHandlersLock)
            {
                eventHandlers.RemoveHandler(sectionName, handler);
            }
        }

        private void OnSourceChanged(object sender, ConfigurationSourceChangedEventArgs e)
        {
            SourceChanged(this, e);
        }
    }

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Marked as answer by sajidalibaig on 11/6/2014 at 3:57 AM
Nov 6, 2014 at 11:57 AM
Thanks Randy, This worked for us with small change.