@@ -204,7 +204,8 @@ public void Dispose()
204204
205205 #region Switch Value Getters and Setters
206206
207- // These properties get or set the like-named underlying switch field value.
207+ // These properties get the like-named underlying switch *property* value and set the underlying
208+ // switch *field* value. This allows tests to verify the default switch values.
208209 //
209210 // They all throw if the value cannot be retrieved or set.
210211
@@ -214,7 +215,7 @@ public void Dispose()
214215 /// </summary>
215216 public bool ? DisableTnirByDefault
216217 {
217- get => GetSwitchValue ( "s_disableTnirByDefault" ) ;
218+ get => GetSwitchPropertyValue ( nameof ( DisableTnirByDefault ) ) ;
218219 set => SetSwitchValue ( "s_disableTnirByDefault" , value ) ;
219220 }
220221 #endif
@@ -224,7 +225,7 @@ public bool? DisableTnirByDefault
224225 /// </summary>
225226 public bool ? EnableMultiSubnetFailoverByDefault
226227 {
227- get => GetSwitchValue ( "s_enableMultiSubnetFailoverByDefault" ) ;
228+ get => GetSwitchPropertyValue ( nameof ( EnableMultiSubnetFailoverByDefault ) ) ;
228229 set => SetSwitchValue ( "s_enableMultiSubnetFailoverByDefault" , value ) ;
229230 }
230231
@@ -234,7 +235,7 @@ public bool? EnableMultiSubnetFailoverByDefault
234235 /// </summary>
235236 public bool ? GlobalizationInvariantMode
236237 {
237- get => GetSwitchValue ( "s_globalizationInvariantMode" ) ;
238+ get => GetSwitchPropertyValue ( nameof ( GlobalizationInvariantMode ) ) ;
238239 set => SetSwitchValue ( "s_globalizationInvariantMode" , value ) ;
239240 }
240241 #endif
@@ -244,7 +245,7 @@ public bool? GlobalizationInvariantMode
244245 /// </summary>
245246 public bool ? IgnoreServerProvidedFailoverPartner
246247 {
247- get => GetSwitchValue ( "s_ignoreServerProvidedFailoverPartner" ) ;
248+ get => GetSwitchPropertyValue ( nameof ( IgnoreServerProvidedFailoverPartner ) ) ;
248249 set => SetSwitchValue ( "s_ignoreServerProvidedFailoverPartner" , value ) ;
249250 }
250251
@@ -253,7 +254,7 @@ public bool? IgnoreServerProvidedFailoverPartner
253254 /// </summary>
254255 public bool ? UseLegacyFailoverAlternationOnLoginSqlErrors
255256 {
256- get => GetSwitchValue ( "s_useLegacyFailoverAlternationOnLoginSqlErrors" ) ;
257+ get => GetSwitchPropertyValue ( nameof ( UseLegacyFailoverAlternationOnLoginSqlErrors ) ) ;
257258 set => SetSwitchValue ( "s_useLegacyFailoverAlternationOnLoginSqlErrors" , value ) ;
258259 }
259260
@@ -262,7 +263,7 @@ public bool? UseLegacyFailoverAlternationOnLoginSqlErrors
262263 /// </summary>
263264 public bool ? LegacyRowVersionNullBehavior
264265 {
265- get => GetSwitchValue ( "s_legacyRowVersionNullBehavior" ) ;
266+ get => GetSwitchPropertyValue ( nameof ( LegacyRowVersionNullBehavior ) ) ;
266267 set => SetSwitchValue ( "s_legacyRowVersionNullBehavior" , value ) ;
267268 }
268269
@@ -271,7 +272,7 @@ public bool? LegacyRowVersionNullBehavior
271272 /// </summary>
272273 public bool ? LegacyVarTimeZeroScaleBehaviour
273274 {
274- get => GetSwitchValue ( "s_legacyVarTimeZeroScaleBehaviour" ) ;
275+ get => GetSwitchPropertyValue ( nameof ( LegacyVarTimeZeroScaleBehaviour ) ) ;
275276 set => SetSwitchValue ( "s_legacyVarTimeZeroScaleBehaviour" , value ) ;
276277 }
277278
@@ -280,7 +281,7 @@ public bool? LegacyVarTimeZeroScaleBehaviour
280281 /// </summary>
281282 public bool ? MakeReadAsyncBlocking
282283 {
283- get => GetSwitchValue ( "s_makeReadAsyncBlocking" ) ;
284+ get => GetSwitchPropertyValue ( nameof ( MakeReadAsyncBlocking ) ) ;
284285 set => SetSwitchValue ( "s_makeReadAsyncBlocking" , value ) ;
285286 }
286287
@@ -289,7 +290,7 @@ public bool? MakeReadAsyncBlocking
289290 /// </summary>
290291 public bool ? SuppressInsecureTlsWarning
291292 {
292- get => GetSwitchValue ( "s_suppressInsecureTlsWarning" ) ;
293+ get => GetSwitchPropertyValue ( nameof ( SuppressInsecureTlsWarning ) ) ;
293294 set => SetSwitchValue ( "s_suppressInsecureTlsWarning" , value ) ;
294295 }
295296
@@ -298,7 +299,7 @@ public bool? SuppressInsecureTlsWarning
298299 /// </summary>
299300 public bool ? TruncateScaledDecimal
300301 {
301- get => GetSwitchValue ( "s_truncateScaledDecimal" ) ;
302+ get => GetSwitchPropertyValue ( nameof ( TruncateScaledDecimal ) ) ;
302303 set => SetSwitchValue ( "s_truncateScaledDecimal" , value ) ;
303304 }
304305
@@ -307,7 +308,7 @@ public bool? TruncateScaledDecimal
307308 /// </summary>
308309 public bool ? UseCompatibilityAsyncBehaviour
309310 {
310- get => GetSwitchValue ( "s_useCompatibilityAsyncBehaviour" ) ;
311+ get => GetSwitchPropertyValue ( nameof ( UseCompatibilityAsyncBehaviour ) ) ;
311312 set => SetSwitchValue ( "s_useCompatibilityAsyncBehaviour" , value ) ;
312313 }
313314
@@ -316,7 +317,7 @@ public bool? UseCompatibilityAsyncBehaviour
316317 /// </summary>
317318 public bool ? UseCompatibilityProcessSni
318319 {
319- get => GetSwitchValue ( "s_useCompatibilityProcessSni" ) ;
320+ get => GetSwitchPropertyValue ( nameof ( UseCompatibilityProcessSni ) ) ;
320321 set => SetSwitchValue ( "s_useCompatibilityProcessSni" , value ) ;
321322 }
322323
@@ -325,7 +326,7 @@ public bool? UseCompatibilityProcessSni
325326 /// </summary>
326327 public bool ? UseConnectionPoolV2
327328 {
328- get => GetSwitchValue ( "s_useConnectionPoolV2" ) ;
329+ get => GetSwitchPropertyValue ( nameof ( UseConnectionPoolV2 ) ) ;
329330 set => SetSwitchValue ( "s_useConnectionPoolV2" , value ) ;
330331 }
331332
@@ -335,7 +336,7 @@ public bool? UseConnectionPoolV2
335336 /// </summary>
336337 public bool ? UseManagedNetworking
337338 {
338- get => GetSwitchValue ( "s_useManagedNetworking" ) ;
339+ get => GetSwitchPropertyValue ( nameof ( UseManagedNetworking ) ) ;
339340 set => SetSwitchValue ( "s_useManagedNetworking" , value ) ;
340341 }
341342 #endif
@@ -345,7 +346,7 @@ public bool? UseManagedNetworking
345346 /// </summary>
346347 public bool ? UseMinimumLoginTimeout
347348 {
348- get => GetSwitchValue ( "s_useMinimumLoginTimeout" ) ;
349+ get => GetSwitchPropertyValue ( nameof ( UseMinimumLoginTimeout ) ) ;
349350 set => SetSwitchValue ( "s_useMinimumLoginTimeout" , value ) ;
350351 }
351352
@@ -358,19 +359,7 @@ public bool? UseMinimumLoginTimeout
358359 /// </summary>
359360 private static bool ? GetSwitchValue ( string fieldName )
360361 {
361- var assembly = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
362- if ( assembly is null )
363- {
364- throw new InvalidOperationException (
365- "Could not get assembly for Microsoft.Data.SqlClient" ) ;
366- }
367-
368- var type = assembly . GetType ( "Microsoft.Data.SqlClient.LocalAppContextSwitches" ) ;
369- if ( type is null )
370- {
371- throw new InvalidOperationException (
372- "Could not get type LocalAppContextSwitches" ) ;
373- }
362+ var type = GetLocalAppContextSwitchesType ( ) ;
374363
375364 var field = type . GetField (
376365 fieldName ,
@@ -405,19 +394,7 @@ public bool? UseMinimumLoginTimeout
405394 /// </summary>
406395 private static void SetSwitchValue ( string fieldName , bool ? value )
407396 {
408- var assembly = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
409- if ( assembly is null )
410- {
411- throw new InvalidOperationException (
412- "Could not get assembly for Microsoft.Data.SqlClient" ) ;
413- }
414-
415- var type = assembly . GetType ( "Microsoft.Data.SqlClient.LocalAppContextSwitches" ) ;
416- if ( type is null )
417- {
418- throw new InvalidOperationException (
419- "Could not get type LocalAppContextSwitches" ) ;
420- }
397+ var type = GetLocalAppContextSwitchesType ( ) ;
421398
422399 var field = type . GetField (
423400 fieldName ,
@@ -442,5 +419,49 @@ private static void SetSwitchValue(string fieldName, bool? value)
442419 field . SetValue ( null , Enum . ToObject ( field . FieldType , byteValue ) ) ;
443420 }
444421
422+ /// <summary>
423+ /// Use reflection to get a switch property value from LocalAppContextSwitches.
424+ /// </summary>
425+ /// <remarks>
426+ /// Each property in LocalAppContextSwitchHelper corresponds to a like-named property in
427+ /// LocalAppContextSwitches, which may return a different value when the AppContext switch
428+ /// has not been set.
429+ /// </remarks>
430+ private static bool GetSwitchPropertyValue ( string propertyName )
431+ {
432+ var type = GetLocalAppContextSwitchesType ( ) ;
433+ var property = type . GetProperty (
434+ propertyName ,
435+ BindingFlags . Static | BindingFlags . Public ) ;
436+
437+ if ( property == null )
438+ {
439+ throw new InvalidOperationException (
440+ $ "Property '{ propertyName } ' not found in LocalAppContextSwitches") ;
441+ }
442+
443+ object ? value = property . GetValue ( null ) ;
444+
445+ return value is bool boolValue
446+ ? boolValue
447+ : throw new InvalidOperationException ( $ "Property '{ propertyName } ' is not of type bool.") ;
448+ }
449+
450+ private static Type GetLocalAppContextSwitchesType ( )
451+ {
452+ var assembly = Assembly . GetAssembly ( typeof ( SqlConnection ) ) ;
453+ if ( assembly is null )
454+ {
455+ throw new InvalidOperationException ( "Could not get assembly for Microsoft.Data.SqlClient" ) ;
456+ }
457+
458+ var type = assembly . GetType ( "Microsoft.Data.SqlClient.LocalAppContextSwitches" ) ;
459+ if ( type is null )
460+ {
461+ throw new InvalidOperationException ( "Could not get type LocalAppContextSwitches" ) ;
462+ }
463+ return type ;
464+ }
465+
445466 #endregion
446467}
0 commit comments