Skip to content

Commit a2c4e15

Browse files
committed
Allow provider-style initialization for section handlers.
1 parent f1f8e1a commit a2c4e15

3 files changed

Lines changed: 42 additions & 6 deletions

File tree

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Version 2 is here with some new features:
1919
* Base Optional Tag - The [optional](#optional) tag that some of the builders in this project employed in V1 has been moved into the base class and is now available
2020
on all key/value config builders.
2121
* Section Handlers - This feature allows users to develop extensions that will apply key/value config to sections other than `appSettings` and `connectionStrings`
22-
if desired. Read more about this feature in the [Section Handlers](#sectionhandlers) segment below.
22+
if desired. Read more about this feature in the [Section Handlers](#section-handlers) segment below.
2323

2424
## Key/Value Config Builders
2525

@@ -339,7 +339,25 @@ collection. As an example, here is what their explicit declaration would look li
339339
</handlers>
340340
</Microsoft.Configuration.ConfigurationBuilders.SectionHandlers>
341341
```
342-
When adding additional handlers, the name of the section must be 'Microsoft.Configuration.ConfigurationBuilders.SectionHandlers' so key/value config builders can find it.
342+
When adding additional handlers, the name of this section must be 'Microsoft.Configuration.ConfigurationBuilders.SectionHandlers' so key/value config builders can find it.
343+
Also note that a more qualified type will be required so the runtime can determine which assembly contains the new handler type. When working
344+
with ASP.Net applications, it is hit and miss regarding whether its able to define new section handlers in `App_Code` or not. Some configuration
345+
sections (such as `appSettings`) get loaded by ASP.Net before `App_Code` is compiled, so handlers for those sections will need to be
346+
compiled in a separate assembly in the 'bin' directory. For example:
347+
```xml
348+
<configSections>
349+
<section name="Microsoft.Configuration.ConfigurationBuilders.SectionHandlers" type="Microsoft.Configuration.ConfigurationBuilders.SectionHandlersSection, Microsoft.Configuration.ConfigurationBuilders.Base" restartOnExternalChanges="false" requirePermission="false" />
350+
</configSections>
351+
352+
<Microsoft.Configuration.ConfigurationBuilders.SectionHandlers>
353+
<handlers>
354+
<remove name="DefaultAppSettingsHandler" />
355+
<add name="DefaultAppSettingsHandler" type="MyCustomAppSettingsSectionHandler, RefAssemblyInBin" />
356+
<remove name="DefaultConnectionStringsHandler" />
357+
<add name="DefaultConnectionStringsHandler" type="MyCustomConnectionStringsSectionHandler, App_Code" />
358+
</handlers>
359+
</Microsoft.Configuration.ConfigurationBuilders.SectionHandlers>
360+
```
343361

344362
## Implementing More Key/Value Config Builders
345363

src/Base/SectionHandler.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
using System.Configuration;
55
using System.Collections.Generic;
6+
using System.Configuration.Provider;
7+
using System.Collections.Specialized;
8+
using System;
69

710
namespace Microsoft.Configuration.ConfigurationBuilders
811
{
@@ -17,7 +20,7 @@ internal interface ISectionHandler
1720
/// A class to be used by <see cref="KeyValueConfigBuilder"/>s to apply key/value config pairs to .Net configuration sections.
1821
/// </summary>
1922
/// <typeparam name="T">The type of <see cref="ConfigurationSection"/> that the implementing class can process.</typeparam>
20-
public abstract class SectionHandler<T> : ISectionHandler where T : ConfigurationSection
23+
public abstract class SectionHandler<T> : ProviderBase, ISectionHandler where T : ConfigurationSection
2124
{
2225
/// <summary>
2326
/// The <see cref="ConfigurationSection"/> instance being processed by this <see cref="SectionHandler{T}"/>.
@@ -41,6 +44,12 @@ public abstract class SectionHandler<T> : ISectionHandler where T : Configuratio
4144
/// <param name="oldKey">The old key name for the config item, or null.</param>
4245
/// <param name="oldItem">A reference to the old key/value pair obtained by <see cref="GetEnumerator"/>, or null.</param>
4346
public abstract void InsertOrUpdate(string newKey, string newValue, string oldKey = null, object oldItem = null);
47+
48+
private void Initialize(string name, T configSection, NameValueCollection config)
49+
{
50+
ConfigSection = configSection;
51+
Initialize(name, config);
52+
}
4453
}
4554

4655
/// <summary>

src/Base/SectionHandlerSection.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Licensed under the MIT license. See the License.txt file in the project root for full license information.
33

44
using System;
5+
using System.Collections.Specialized;
56
using System.Configuration;
7+
using System.Reflection;
68

79
namespace Microsoft.Configuration.ConfigurationBuilders
810
{
@@ -62,13 +64,20 @@ static internal ISectionHandler GetSectionHandler<T>(T configSection) where T :
6264
ISectionHandler handler = Activator.CreateInstance(handlerType) as ISectionHandler;
6365
if (handler != null)
6466
{
65-
sectionHandlerDesiredType.GetProperty("ConfigSection").SetValue(handler, configSection);
67+
ProviderSettings settings = handlerSection.Handlers[i];
68+
NameValueCollection clonedParams = new NameValueCollection(settings.Parameters.Count);
69+
foreach (string key in settings.Parameters)
70+
clonedParams[key] = settings.Parameters[key];
71+
72+
MethodInfo init = sectionHandlerDesiredType.GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance);
73+
init.Invoke(handler, new object[] { settings.Name, configSection, clonedParams });
74+
75+
return handler;
6676
}
67-
return handler;
6877
}
6978
}
7079

71-
return null;
80+
throw new Exception($"Error in Configuration: Cannot find ISectionHandler for '{configSection.SectionInformation.Name}' section.");
7281
}
7382
}
7483
}

0 commit comments

Comments
 (0)