7
7
using System . Diagnostics . CodeAnalysis ;
8
8
using System . Globalization ;
9
9
using System . Reflection ;
10
+ using System . Text ;
11
+ using System . Text . Json ;
10
12
11
13
namespace Microsoft . AspNetCore . Components
12
14
{
@@ -523,7 +525,7 @@ public static bool TryConvertToString(object? obj, CultureInfo? culture, out str
523
525
return ConvertToStringCore ( obj , culture , out value ) ;
524
526
}
525
527
526
- internal readonly static BindParser < string ? > ConvertToString = ConvertToStringCore ;
528
+ internal static readonly BindParser < string ? > ConvertToString = ConvertToStringCore ;
527
529
528
530
private static bool ConvertToStringCore ( object ? obj , CultureInfo ? culture , out string ? value )
529
531
{
@@ -556,8 +558,8 @@ public static bool TryConvertToNullableBool(object? obj, CultureInfo? culture, o
556
558
return ConvertToNullableBoolCore ( obj , culture , out value ) ;
557
559
}
558
560
559
- internal readonly static BindParser < bool > ConvertToBool = ConvertToBoolCore ;
560
- internal readonly static BindParser < bool ? > ConvertToNullableBool = ConvertToNullableBoolCore ;
561
+ internal static readonly BindParser < bool > ConvertToBool = ConvertToBoolCore ;
562
+ internal static readonly BindParser < bool ? > ConvertToNullableBool = ConvertToNullableBoolCore ;
561
563
562
564
private static bool ConvertToBoolCore ( object ? obj , CultureInfo ? culture , out bool value )
563
565
{
@@ -1278,8 +1280,18 @@ private static bool ConvertToNullableEnum<T>(object? obj, CultureInfo? culture,
1278
1280
1279
1281
private static class FormatterDelegateCache
1280
1282
{
1281
- private readonly static ConcurrentDictionary < Type , Delegate > _cache = new ConcurrentDictionary < Type , Delegate > ( ) ;
1283
+ private static readonly ConcurrentDictionary < Type , Delegate > _cache = new ConcurrentDictionary < Type , Delegate > ( ) ;
1282
1284
1285
+ private static MethodInfo ? _makeArrayFormatter ;
1286
+
1287
+ [ UnconditionalSuppressMessage (
1288
+ "ReflectionAnalysis" ,
1289
+ "IL2060:MakeGenericMethod" ,
1290
+ Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727" ) ]
1291
+ [ UnconditionalSuppressMessage (
1292
+ "ReflectionAnalysis" ,
1293
+ "IL2075:MakeGenericMethod" ,
1294
+ Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727" ) ]
1283
1295
public static BindFormatter < T > Get < [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . All ) ] T > ( )
1284
1296
{
1285
1297
if ( ! _cache . TryGetValue ( typeof ( T ) , out var formatter ) )
@@ -1366,6 +1378,12 @@ private static class FormatterDelegateCache
1366
1378
{
1367
1379
formatter = ( BindFormatter < T > ) FormatEnumValueCore < T > ;
1368
1380
}
1381
+ else if ( typeof ( T ) . IsArray )
1382
+ {
1383
+ var method = _makeArrayFormatter ??= typeof ( FormatterDelegateCache ) . GetMethod ( nameof ( MakeArrayFormatter ) , BindingFlags . NonPublic | BindingFlags . Static ) ! ;
1384
+ var elementType = typeof ( T ) . GetElementType ( ) ! ;
1385
+ formatter = ( Delegate ) method . MakeGenericMethod ( elementType ) . Invoke ( null , null ) ! ;
1386
+ }
1369
1387
else
1370
1388
{
1371
1389
formatter = MakeTypeConverterFormatter < T > ( ) ;
@@ -1377,6 +1395,36 @@ private static class FormatterDelegateCache
1377
1395
return ( BindFormatter < T > ) formatter ;
1378
1396
}
1379
1397
1398
+ private static BindFormatter < T [ ] > MakeArrayFormatter < [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . All ) ] T > ( )
1399
+ {
1400
+ var elementFormatter = Get < T > ( ) ;
1401
+
1402
+ return FormatArrayValue ;
1403
+
1404
+ string ? FormatArrayValue ( T [ ] value , CultureInfo ? culture )
1405
+ {
1406
+ if ( value . Length == 0 )
1407
+ {
1408
+ return "[]" ;
1409
+ }
1410
+
1411
+ var builder = new StringBuilder ( "[\" " ) ;
1412
+ builder . Append ( JsonEncodedText . Encode ( elementFormatter ( value [ 0 ] , culture ) ? . ToString ( ) ?? string . Empty ) ) ;
1413
+ builder . Append ( '\" ' ) ;
1414
+
1415
+ for ( var i = 1 ; i < value . Length ; i ++ )
1416
+ {
1417
+ builder . Append ( ", \" " ) ;
1418
+ builder . Append ( JsonEncodedText . Encode ( elementFormatter ( value [ i ] , culture ) ? . ToString ( ) ?? string . Empty ) ) ;
1419
+ builder . Append ( '\" ' ) ;
1420
+ }
1421
+
1422
+ builder . Append ( ']' ) ;
1423
+
1424
+ return builder . ToString ( ) ;
1425
+ }
1426
+ }
1427
+
1380
1428
private static BindFormatter < T > MakeTypeConverterFormatter < [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . All ) ] T > ( )
1381
1429
{
1382
1430
var typeConverter = TypeDescriptor . GetConverter ( typeof ( T ) ) ;
@@ -1400,15 +1448,20 @@ string FormatWithTypeConverter(T value, CultureInfo? culture)
1400
1448
1401
1449
internal static class ParserDelegateCache
1402
1450
{
1403
- private readonly static ConcurrentDictionary < Type , Delegate > _cache = new ConcurrentDictionary < Type , Delegate > ( ) ;
1451
+ private static readonly ConcurrentDictionary < Type , Delegate > _cache = new ConcurrentDictionary < Type , Delegate > ( ) ;
1404
1452
1405
1453
private static MethodInfo ? _convertToEnum ;
1406
1454
private static MethodInfo ? _convertToNullableEnum ;
1455
+ private static MethodInfo ? _makeArrayTypeConverter ;
1407
1456
1408
1457
[ UnconditionalSuppressMessage (
1409
1458
"ReflectionAnalysis" ,
1410
1459
"IL2060:MakeGenericMethod" ,
1411
1460
Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727" ) ]
1461
+ [ UnconditionalSuppressMessage (
1462
+ "ReflectionAnalysis" ,
1463
+ "IL2075:MakeGenericMethod" ,
1464
+ Justification = "The referenced methods don't have any DynamicallyAccessedMembers annotations. See https://github.com/mono/linker/issues/1727" ) ]
1412
1465
public static BindParser < T > Get < [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . All ) ] T > ( )
1413
1466
{
1414
1467
if ( ! _cache . TryGetValue ( typeof ( T ) , out var parser ) )
@@ -1503,6 +1556,12 @@ internal static class ParserDelegateCache
1503
1556
var method = _convertToNullableEnum ??= typeof ( BindConverter ) . GetMethod ( nameof ( ConvertToNullableEnum ) , BindingFlags . NonPublic | BindingFlags . Static ) ! ;
1504
1557
parser = method . MakeGenericMethod ( innerType ) . CreateDelegate ( typeof ( BindParser < T > ) , target : null ) ;
1505
1558
}
1559
+ else if ( typeof ( T ) . IsArray )
1560
+ {
1561
+ var method = _makeArrayTypeConverter ??= typeof ( ParserDelegateCache ) . GetMethod ( nameof ( MakeArrayTypeConverter ) , BindingFlags . NonPublic | BindingFlags . Static ) ! ;
1562
+ var elementType = typeof ( T ) . GetElementType ( ) ! ;
1563
+ parser = ( Delegate ) method . MakeGenericMethod ( elementType ) . Invoke ( null , null ) ! ;
1564
+ }
1506
1565
else
1507
1566
{
1508
1567
parser = MakeTypeConverterConverter < T > ( ) ;
@@ -1514,6 +1573,36 @@ internal static class ParserDelegateCache
1514
1573
return ( BindParser < T > ) parser ;
1515
1574
}
1516
1575
1576
+ private static BindParser < T [ ] ? > MakeArrayTypeConverter < [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . All ) ] T > ( )
1577
+ {
1578
+ var elementParser = Get < T > ( ) ;
1579
+
1580
+ return ConvertToArray ;
1581
+
1582
+ bool ConvertToArray ( object ? obj , CultureInfo ? culture , out T [ ] ? value )
1583
+ {
1584
+ if ( obj is not Array initialArray )
1585
+ {
1586
+ value = default ;
1587
+ return false ;
1588
+ }
1589
+
1590
+ var convertedArray = new T [ initialArray . Length ] ;
1591
+
1592
+ for ( var i = 0 ; i < initialArray . Length ; i ++ )
1593
+ {
1594
+ if ( ! elementParser ( initialArray . GetValue ( i ) , culture , out convertedArray [ i ] ! ) )
1595
+ {
1596
+ value = default ;
1597
+ return false ;
1598
+ }
1599
+ }
1600
+
1601
+ value = convertedArray ;
1602
+ return true ;
1603
+ }
1604
+ }
1605
+
1517
1606
private static BindParser < T > MakeTypeConverterConverter < [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . All ) ] T > ( )
1518
1607
{
1519
1608
var typeConverter = TypeDescriptor . GetConverter ( typeof ( T ) ) ;
0 commit comments