66using System . Configuration . Provider ;
77using System . Collections . Specialized ;
88using System ;
9+ using System . Linq . Expressions ;
910
1011namespace Microsoft . Configuration . ConfigurationBuilders
1112{
@@ -14,6 +15,7 @@ internal interface ISectionHandler
1415 {
1516 void InsertOrUpdate ( string newKey , string newValue , string oldKey = null , object oldItem = null ) ;
1617 IEnumerator < KeyValuePair < string , object > > GetEnumerator ( ) ;
18+ string TryGetOriginalCase ( string requestedKey ) ;
1719 }
1820
1921 /// <summary>
@@ -45,6 +47,17 @@ public abstract class SectionHandler<T> : ProviderBase, ISectionHandler where T
4547 /// <param name="oldItem">A reference to the old key/value pair obtained by <see cref="GetEnumerator"/>, or null.</param>
4648 public abstract void InsertOrUpdate ( string newKey , string newValue , string oldKey = null , object oldItem = null ) ;
4749
50+ /// <summary>
51+ /// Attempt to lookup the original key casing so it can be preserved during greedy updates which would otherwise lose
52+ /// the original casing in favor of the casing used in the config source.
53+ /// </summary>
54+ /// <param name="requestedKey">The key to find original casing for.</param>
55+ /// <returns>Unless overridden, returns the string passed in.</returns>
56+ public virtual string TryGetOriginalCase ( string requestedKey )
57+ {
58+ return requestedKey ;
59+ }
60+
4861 private void Initialize ( string name , T configSection , NameValueCollection config )
4962 {
5063 ConfigSection = configSection ;
@@ -88,6 +101,25 @@ public override IEnumerator<KeyValuePair<string, object>> GetEnumerator()
88101 foreach ( string key in keys )
89102 yield return new KeyValuePair < string , object > ( key , key ) ;
90103 }
104+
105+ /// <summary>
106+ /// Attempt to lookup the original key casing so it can be preserved during greedy updates which would otherwise lose
107+ /// the original casing in favor of the casing used in the config source.
108+ /// </summary>
109+ /// <param name="requestedKey">The key to find original casing for.</param>
110+ /// <returns>A string containing the key with original casing from the config section, or the key as passed in if no match
111+ /// can be found.</returns>
112+ public override string TryGetOriginalCase ( string requestedKey )
113+ {
114+ if ( ! String . IsNullOrWhiteSpace ( requestedKey ) )
115+ {
116+ var keyval = ConfigSection . Settings [ requestedKey ] ;
117+ if ( keyval != null )
118+ return keyval . Key ;
119+ }
120+
121+ return base . TryGetOriginalCase ( requestedKey ) ;
122+ }
91123 }
92124
93125 /// <summary>
@@ -136,5 +168,24 @@ public override IEnumerator<KeyValuePair<string, object>> GetEnumerator()
136168 foreach ( ConnectionStringSettings cs in connStrs )
137169 yield return new KeyValuePair < string , object > ( cs . Name , cs ) ;
138170 }
171+
172+ /// <summary>
173+ /// Attempt to lookup the original key casing so it can be preserved during greedy updates which would otherwise lose
174+ /// the original casing in favor of the casing used in the config source.
175+ /// </summary>
176+ /// <param name="requestedKey">The key to find original casing for.</param>
177+ /// <returns>A string containing the key with original casing from the config section, or the key as passed in if no match
178+ /// can be found.</returns>
179+ public override string TryGetOriginalCase ( string requestedKey )
180+ {
181+ if ( ! String . IsNullOrWhiteSpace ( requestedKey ) )
182+ {
183+ var connStr = ConfigSection . ConnectionStrings [ requestedKey ] ;
184+ if ( connStr != null )
185+ return connStr . Name ;
186+ }
187+
188+ return base . TryGetOriginalCase ( requestedKey ) ;
189+ }
139190 }
140191}
0 commit comments