@@ -77,6 +77,7 @@ public void FindTryParseStringMethod_ReturnsTheExpectedTryParseMethodWithInvaria
77
77
[ Theory ]
78
78
[ InlineData ( typeof ( TryParseStringRecord ) ) ]
79
79
[ InlineData ( typeof ( TryParseStringStruct ) ) ]
80
+ [ InlineData ( typeof ( TryParseInheritClassWithFormatProvider ) ) ]
80
81
public void FindTryParseStringMethod_ReturnsTheExpectedTryParseMethodWithInvariantCultureCustomType ( Type type )
81
82
{
82
83
var methodFound = new ParameterBindingMethodCache ( ) . FindTryParseMethod ( @type ) ;
@@ -94,6 +95,24 @@ public void FindTryParseStringMethod_ReturnsTheExpectedTryParseMethodWithInvaria
94
95
Assert . True ( ( ( call . Arguments [ 1 ] as ConstantExpression ) ! . Value as CultureInfo ) ! . Equals ( CultureInfo . InvariantCulture ) ) ;
95
96
}
96
97
98
+ [ Theory ]
99
+ [ InlineData ( typeof ( TryParseNoFormatProviderRecord ) ) ]
100
+ [ InlineData ( typeof ( TryParseNoFormatProviderStruct ) ) ]
101
+ [ InlineData ( typeof ( TryParseInheritClass ) ) ]
102
+ public void FindTryParseMethod_WithNoFormatProvider ( Type type )
103
+ {
104
+ var methodFound = new ParameterBindingMethodCache ( ) . FindTryParseMethod ( @type ) ;
105
+ Assert . NotNull ( methodFound ) ;
106
+
107
+ var call = methodFound ! ( Expression . Variable ( type , "parsedValue" ) ) as MethodCallExpression ;
108
+ Assert . NotNull ( call ) ;
109
+ var parameters = call ! . Method . GetParameters ( ) ;
110
+
111
+ Assert . Equal ( 2 , parameters . Length ) ;
112
+ Assert . Equal ( typeof ( string ) , parameters [ 0 ] . ParameterType ) ;
113
+ Assert . True ( parameters [ 1 ] . IsOut ) ;
114
+ }
115
+
97
116
public static IEnumerable < object [ ] > TryParseStringParameterInfoData
98
117
{
99
118
get
@@ -249,6 +268,14 @@ public static IEnumerable<object[]> BindAsyncParameterInfoData
249
268
new [ ]
250
269
{
251
270
GetFirstParameter ( ( BindAsyncSingleArgStruct arg ) => BindAsyncSingleArgStructMethod ( arg ) ) ,
271
+ } ,
272
+ new [ ]
273
+ {
274
+ GetFirstParameter ( ( InheritBindAsync arg ) => InheritBindAsyncMethod ( arg ) )
275
+ } ,
276
+ new [ ]
277
+ {
278
+ GetFirstParameter ( ( InheritBindAsyncWithParameterInfo arg ) => InheritBindAsyncWithParameterInfoMethod ( arg ) )
252
279
}
253
280
} ;
254
281
}
@@ -285,6 +312,7 @@ public void FindBindAsyncMethod_FindsNonNullableReturningBindAsyncMethodGivenNul
285
312
[ InlineData ( typeof ( InvalidTooFewArgsTryParseClass ) ) ]
286
313
[ InlineData ( typeof ( InvalidNonStaticTryParseStruct ) ) ]
287
314
[ InlineData ( typeof ( InvalidNonStaticTryParseClass ) ) ]
315
+ [ InlineData ( typeof ( TryParseWrongTypeInheritClass ) ) ]
288
316
public void FindTryParseMethod_ThrowsIfInvalidTryParseOnType ( Type type )
289
317
{
290
318
var ex = Assert . Throws < InvalidOperationException > (
@@ -308,6 +336,8 @@ public void FindTryParseMethod_IgnoresInvalidTryParseIfGoodOneFound(Type type)
308
336
[ InlineData ( typeof ( InvalidWrongReturnBindAsyncClass ) ) ]
309
337
[ InlineData ( typeof ( InvalidWrongParamBindAsyncStruct ) ) ]
310
338
[ InlineData ( typeof ( InvalidWrongParamBindAsyncClass ) ) ]
339
+ [ InlineData ( typeof ( BindAsyncWrongTypeInherit ) ) ]
340
+ [ InlineData ( typeof ( BindAsyncWithParameterInfoWrongTypeInherit ) ) ]
311
341
public void FindBindAsyncMethod_ThrowsIfInvalidBindAsyncOnType ( Type type )
312
342
{
313
343
var cache = new ParameterBindingMethodCache ( ) ;
@@ -350,6 +380,8 @@ private static void NullableReturningBindAsyncStructMethod(NullableReturningBind
350
380
351
381
private static void BindAsyncSingleArgRecordMethod ( BindAsyncSingleArgRecord arg ) { }
352
382
private static void BindAsyncSingleArgStructMethod ( BindAsyncSingleArgStruct arg ) { }
383
+ private static void InheritBindAsyncMethod ( InheritBindAsync arg ) { }
384
+ private static void InheritBindAsyncWithParameterInfoMethod ( InheritBindAsyncWithParameterInfo args ) { }
353
385
354
386
private static ParameterInfo GetFirstParameter < T > ( Expression < Action < T > > expr )
355
387
{
@@ -538,6 +570,67 @@ public bool TryParse(string? value, IFormatProvider formatProvider, out InvalidN
538
570
}
539
571
}
540
572
573
+ private record TryParseNoFormatProviderRecord ( int Value )
574
+ {
575
+ public static bool TryParse ( string ? value , out TryParseNoFormatProviderRecord ? result )
576
+ {
577
+ if ( ! int . TryParse ( value , out var val ) )
578
+ {
579
+ result = null ;
580
+ return false ;
581
+ }
582
+
583
+ result = new TryParseNoFormatProviderRecord ( val ) ;
584
+ return true ;
585
+ }
586
+ }
587
+
588
+ private record struct TryParseNoFormatProviderStruct ( int Value )
589
+ {
590
+ public static bool TryParse ( string ? value , out TryParseNoFormatProviderStruct result )
591
+ {
592
+ if ( ! int . TryParse ( value , out var val ) )
593
+ {
594
+ result = default ;
595
+ return false ;
596
+ }
597
+
598
+ result = new TryParseNoFormatProviderStruct ( val ) ;
599
+ return true ;
600
+ }
601
+ }
602
+
603
+ private class BaseTryParseClass < T >
604
+ {
605
+ public static bool TryParse ( string ? value , out T ? result )
606
+ {
607
+ result = default ( T ) ;
608
+ return false ;
609
+ }
610
+ }
611
+
612
+ private class TryParseInheritClass : BaseTryParseClass < TryParseInheritClass >
613
+ {
614
+ }
615
+
616
+ // using wrong T on purpose
617
+ private class TryParseWrongTypeInheritClass : BaseTryParseClass < TryParseInheritClass >
618
+ {
619
+ }
620
+
621
+ private class BaseTryParseClassWithFormatProvider < T >
622
+ {
623
+ public static bool TryParse ( string ? value , IFormatProvider formatProvider , out T ? result )
624
+ {
625
+ result = default ( T ) ;
626
+ return false ;
627
+ }
628
+ }
629
+
630
+ private class TryParseInheritClassWithFormatProvider : BaseTryParseClassWithFormatProvider < TryParseInheritClassWithFormatProvider >
631
+ {
632
+ }
633
+
541
634
private record BindAsyncRecord ( int Value )
542
635
{
543
636
public static ValueTask < BindAsyncRecord ? > BindAsync ( HttpContext context , ParameterInfo parameter )
@@ -644,6 +737,40 @@ public static ValueTask<BindAsyncClassWithGoodAndBad> BindAsync(ParameterInfo pa
644
737
throw new NotImplementedException ( ) ;
645
738
}
646
739
740
+ private class BaseBindAsync < T >
741
+ {
742
+ public static ValueTask < T ? > BindAsync ( HttpContext context )
743
+ {
744
+ return new ( default ( T ) ) ;
745
+ }
746
+ }
747
+
748
+ private class InheritBindAsync : BaseBindAsync < InheritBindAsync >
749
+ {
750
+ }
751
+
752
+ // Using wrong T on purpose
753
+ private class BindAsyncWrongTypeInherit : BaseBindAsync < InheritBindAsync >
754
+ {
755
+ }
756
+
757
+ private class BaseBindAsyncWithParameterInfo < T >
758
+ {
759
+ public static ValueTask < T ? > BindAsync ( HttpContext context , ParameterInfo parameter )
760
+ {
761
+ return new ( default ( T ) ) ;
762
+ }
763
+ }
764
+
765
+ private class InheritBindAsyncWithParameterInfo : BaseBindAsyncWithParameterInfo < InheritBindAsyncWithParameterInfo >
766
+ {
767
+ }
768
+
769
+ // Using wrong T on purpose
770
+ private class BindAsyncWithParameterInfoWrongTypeInherit : BaseBindAsyncWithParameterInfo < InheritBindAsync >
771
+ {
772
+ }
773
+
647
774
private class MockParameterInfo : ParameterInfo
648
775
{
649
776
public MockParameterInfo ( Type type , string name )
0 commit comments