@@ -214,7 +214,8 @@ public void Dispose()
214214
215215 #region Switch Value Getters and Setters
216216
217- // These properties get or set the like-named underlying switch field value.
217+ // These properties get the like-named underlying switch *property* value and set the underlying
218+ // switch *field* value. This allows tests to verify the default switch values.
218219 //
219220 // They all throw if the value cannot be retrieved or set.
220221
@@ -224,7 +225,7 @@ public void Dispose()
224225 /// </summary>
225226 public bool ? DisableTnirByDefault
226227 {
227- get => GetSwitchValue ( "s_disableTnirByDefault" ) ;
228+ get => GetSwitchPropertyValue ( nameof ( DisableTnirByDefault ) ) ;
228229 set => SetSwitchValue ( "s_disableTnirByDefault" , value ) ;
229230 }
230231 #endif
@@ -234,7 +235,7 @@ public bool? DisableTnirByDefault
234235 /// </summary>
235236 public bool ? EnableMultiSubnetFailoverByDefault
236237 {
237- get => GetSwitchValue ( "s_enableMultiSubnetFailoverByDefault" ) ;
238+ get => GetSwitchPropertyValue ( nameof ( EnableMultiSubnetFailoverByDefault ) ) ;
238239 set => SetSwitchValue ( "s_enableMultiSubnetFailoverByDefault" , value ) ;
239240 }
240241
@@ -244,7 +245,7 @@ public bool? EnableMultiSubnetFailoverByDefault
244245 /// </summary>
245246 public bool ? GlobalizationInvariantMode
246247 {
247- get => GetSwitchValue ( "s_globalizationInvariantMode" ) ;
248+ get => GetSwitchPropertyValue ( nameof ( GlobalizationInvariantMode ) ) ;
248249 set => SetSwitchValue ( "s_globalizationInvariantMode" , value ) ;
249250 }
250251 #endif
@@ -254,7 +255,7 @@ public bool? GlobalizationInvariantMode
254255 /// </summary>
255256 public bool ? IgnoreServerProvidedFailoverPartner
256257 {
257- get => GetSwitchValue ( "s_ignoreServerProvidedFailoverPartner" ) ;
258+ get => GetSwitchPropertyValue ( nameof ( IgnoreServerProvidedFailoverPartner ) ) ;
258259 set => SetSwitchValue ( "s_ignoreServerProvidedFailoverPartner" , value ) ;
259260 }
260261
@@ -263,7 +264,7 @@ public bool? IgnoreServerProvidedFailoverPartner
263264 /// </summary>
264265 public bool ? UseLegacyFailoverAlternationOnLoginSqlErrors
265266 {
266- get => GetSwitchValue ( "s_useLegacyFailoverAlternationOnLoginSqlErrors" ) ;
267+ get => GetSwitchPropertyValue ( nameof ( UseLegacyFailoverAlternationOnLoginSqlErrors ) ) ;
267268 set => SetSwitchValue ( "s_useLegacyFailoverAlternationOnLoginSqlErrors" , value ) ;
268269 }
269270
@@ -272,7 +273,7 @@ public bool? UseLegacyFailoverAlternationOnLoginSqlErrors
272273 /// </summary>
273274 public bool ? LegacyRowVersionNullBehavior
274275 {
275- get => GetSwitchValue ( "s_legacyRowVersionNullBehavior" ) ;
276+ get => GetSwitchPropertyValue ( nameof ( LegacyRowVersionNullBehavior ) ) ;
276277 set => SetSwitchValue ( "s_legacyRowVersionNullBehavior" , value ) ;
277278 }
278279
@@ -281,7 +282,7 @@ public bool? LegacyRowVersionNullBehavior
281282 /// </summary>
282283 public bool ? LegacyVarTimeZeroScaleBehaviour
283284 {
284- get => GetSwitchValue ( "s_legacyVarTimeZeroScaleBehaviour" ) ;
285+ get => GetSwitchPropertyValue ( nameof ( LegacyVarTimeZeroScaleBehaviour ) ) ;
285286 set => SetSwitchValue ( "s_legacyVarTimeZeroScaleBehaviour" , value ) ;
286287 }
287288
@@ -290,7 +291,7 @@ public bool? LegacyVarTimeZeroScaleBehaviour
290291 /// </summary>
291292 public bool ? MakeReadAsyncBlocking
292293 {
293- get => GetSwitchValue ( "s_makeReadAsyncBlocking" ) ;
294+ get => GetSwitchPropertyValue ( nameof ( MakeReadAsyncBlocking ) ) ;
294295 set => SetSwitchValue ( "s_makeReadAsyncBlocking" , value ) ;
295296 }
296297
@@ -299,7 +300,7 @@ public bool? MakeReadAsyncBlocking
299300 /// </summary>
300301 public bool ? SuppressInsecureTlsWarning
301302 {
302- get => GetSwitchValue ( "s_suppressInsecureTlsWarning" ) ;
303+ get => GetSwitchPropertyValue ( nameof ( SuppressInsecureTlsWarning ) ) ;
303304 set => SetSwitchValue ( "s_suppressInsecureTlsWarning" , value ) ;
304305 }
305306
@@ -308,7 +309,7 @@ public bool? SuppressInsecureTlsWarning
308309 /// </summary>
309310 public bool ? TruncateScaledDecimal
310311 {
311- get => GetSwitchValue ( "s_truncateScaledDecimal" ) ;
312+ get => GetSwitchPropertyValue ( nameof ( TruncateScaledDecimal ) ) ;
312313 set => SetSwitchValue ( "s_truncateScaledDecimal" , value ) ;
313314 }
314315
@@ -317,7 +318,7 @@ public bool? TruncateScaledDecimal
317318 /// </summary>
318319 public bool ? UseCompatibilityAsyncBehaviour
319320 {
320- get => GetSwitchValue ( "s_useCompatibilityAsyncBehaviour" ) ;
321+ get => GetSwitchPropertyValue ( nameof ( UseCompatibilityAsyncBehaviour ) ) ;
321322 set => SetSwitchValue ( "s_useCompatibilityAsyncBehaviour" , value ) ;
322323 }
323324
@@ -326,7 +327,7 @@ public bool? UseCompatibilityAsyncBehaviour
326327 /// </summary>
327328 public bool ? UseCompatibilityProcessSni
328329 {
329- get => GetSwitchValue ( "s_useCompatibilityProcessSni" ) ;
330+ get => GetSwitchPropertyValue ( nameof ( UseCompatibilityProcessSni ) ) ;
330331 set => SetSwitchValue ( "s_useCompatibilityProcessSni" , value ) ;
331332 }
332333
@@ -335,7 +336,7 @@ public bool? UseCompatibilityProcessSni
335336 /// </summary>
336337 public bool ? UseConnectionPoolV2
337338 {
338- get => GetSwitchValue ( "s_useConnectionPoolV2" ) ;
339+ get => GetSwitchPropertyValue ( nameof ( UseConnectionPoolV2 ) ) ;
339340 set => SetSwitchValue ( "s_useConnectionPoolV2" , value ) ;
340341 }
341342
@@ -344,7 +345,7 @@ public bool? UseConnectionPoolV2
344345 /// </summary>
345346 public bool ? UseLegacyIdleTimeoutBehavior
346347 {
347- get => GetSwitchValue ( "s_useLegacyIdleTimeoutBehavior" ) ;
348+ get => GetSwitchPropertyValue ( nameof ( UseLegacyIdleTimeoutBehavior ) ) ;
348349 set => SetSwitchValue ( "s_useLegacyIdleTimeoutBehavior" , value ) ;
349350 }
350351
@@ -353,7 +354,7 @@ public bool? UseLegacyIdleTimeoutBehavior
353354 /// </summary>
354355 public bool ? UseOverallConnectTimeoutForPoolWait
355356 {
356- get => GetSwitchValue ( "s_useOverallConnectTimeoutForPoolWait" ) ;
357+ get => GetSwitchPropertyValue ( nameof ( UseOverallConnectTimeoutForPoolWait ) ) ;
357358 set => SetSwitchValue ( "s_useOverallConnectTimeoutForPoolWait" , value ) ;
358359 }
359360
@@ -363,7 +364,7 @@ public bool? UseOverallConnectTimeoutForPoolWait
363364 /// </summary>
364365 public bool ? UseManagedNetworking
365366 {
366- get => GetSwitchValue ( "s_useManagedNetworking" ) ;
367+ get => GetSwitchPropertyValue ( nameof ( UseManagedNetworking ) ) ;
367368 set => SetSwitchValue ( "s_useManagedNetworking" , value ) ;
368369 }
369370 #endif
@@ -373,7 +374,7 @@ public bool? UseManagedNetworking
373374 /// </summary>
374375 public bool ? UseMinimumLoginTimeout
375376 {
376- get => GetSwitchValue ( "s_useMinimumLoginTimeout" ) ;
377+ get => GetSwitchPropertyValue ( nameof ( UseMinimumLoginTimeout ) ) ;
377378 set => SetSwitchValue ( "s_useMinimumLoginTimeout" , value ) ;
378379 }
379380
@@ -386,19 +387,7 @@ public bool? UseMinimumLoginTimeout
386387 /// </summary>
387388 private static bool ? GetSwitchValue ( string fieldName )
388389 {
389- var assembly = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
390- if ( assembly is null )
391- {
392- throw new InvalidOperationException (
393- "Could not get assembly for Microsoft.Data.SqlClient" ) ;
394- }
395-
396- var type = assembly . GetType ( "Microsoft.Data.SqlClient.LocalAppContextSwitches" ) ;
397- if ( type is null )
398- {
399- throw new InvalidOperationException (
400- "Could not get type LocalAppContextSwitches" ) ;
401- }
390+ var type = GetLocalAppContextSwitchesType ( ) ;
402391
403392 var field = type . GetField (
404393 fieldName ,
@@ -433,19 +422,7 @@ public bool? UseMinimumLoginTimeout
433422 /// </summary>
434423 private static void SetSwitchValue ( string fieldName , bool ? value )
435424 {
436- var assembly = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
437- if ( assembly is null )
438- {
439- throw new InvalidOperationException (
440- "Could not get assembly for Microsoft.Data.SqlClient" ) ;
441- }
442-
443- var type = assembly . GetType ( "Microsoft.Data.SqlClient.LocalAppContextSwitches" ) ;
444- if ( type is null )
445- {
446- throw new InvalidOperationException (
447- "Could not get type LocalAppContextSwitches" ) ;
448- }
425+ var type = GetLocalAppContextSwitchesType ( ) ;
449426
450427 var field = type . GetField (
451428 fieldName ,
@@ -470,5 +447,49 @@ private static void SetSwitchValue(string fieldName, bool? value)
470447 field . SetValue ( null , Enum . ToObject ( field . FieldType , byteValue ) ) ;
471448 }
472449
450+ /// <summary>
451+ /// Use reflection to get a switch property value from LocalAppContextSwitches.
452+ /// </summary>
453+ /// <remarks>
454+ /// Each property in LocalAppContextSwitchHelper corresponds to a like-named property in
455+ /// LocalAppContextSwitches, which may return a different value when the AppContext switch
456+ /// has not been set.
457+ /// </remarks>
458+ private static bool GetSwitchPropertyValue ( string propertyName )
459+ {
460+ var type = GetLocalAppContextSwitchesType ( ) ;
461+ var property = type . GetProperty (
462+ propertyName ,
463+ BindingFlags . Static | BindingFlags . Public ) ;
464+
465+ if ( property == null )
466+ {
467+ throw new InvalidOperationException (
468+ $ "Property '{ propertyName } ' not found in LocalAppContextSwitches") ;
469+ }
470+
471+ object ? value = property . GetValue ( null ) ;
472+
473+ return value is bool boolValue
474+ ? boolValue
475+ : throw new InvalidOperationException ( $ "Property '{ propertyName } ' is not of type bool.") ;
476+ }
477+
478+ private static Type GetLocalAppContextSwitchesType ( )
479+ {
480+ var assembly = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
481+ if ( assembly is null )
482+ {
483+ throw new InvalidOperationException ( "Could not get assembly for Microsoft.Data.SqlClient" ) ;
484+ }
485+
486+ var type = assembly . GetType ( "Microsoft.Data.SqlClient.LocalAppContextSwitches" ) ;
487+ if ( type is null )
488+ {
489+ throw new InvalidOperationException ( "Could not get type LocalAppContextSwitches" ) ;
490+ }
491+ return type ;
492+ }
493+
473494 #endregion
474495}
0 commit comments