@@ -801,6 +801,7 @@ Expression ParseStringLiteral()
801
801
_textParser . NextToken ( ) ;
802
802
return ConstantExpressionHelper . CreateLiteral ( result , result ) ;
803
803
}
804
+
804
805
Expression ParseIntegerLiteral ( )
805
806
{
806
807
_textParser . ValidateToken ( TokenId . IntegerLiteral ) ;
@@ -1025,14 +1026,14 @@ Expression ParseIdentifier()
1025
1026
_externals != null && _externals . TryGetValue ( _textParser . CurrentToken . Text , out value ) ||
1026
1027
_internals . TryGetValue ( _textParser . CurrentToken . Text , out value ) )
1027
1028
{
1028
- Expression expr = value as Expression ;
1029
+ var expr = value as Expression ;
1029
1030
if ( expr == null )
1030
1031
{
1031
1032
expr = Expression . Constant ( value ) ;
1032
1033
}
1033
1034
else
1034
1035
{
1035
- LambdaExpression lambda = expr as LambdaExpression ;
1036
+ var lambda = expr as LambdaExpression ;
1036
1037
if ( lambda != null )
1037
1038
{
1038
1039
return ParseLambdaInvocation ( lambda ) ;
@@ -1338,10 +1339,10 @@ Expression ParseNew()
1338
1339
{
1339
1340
if ( ! TryGetMemberName ( expr , out propName ) )
1340
1341
{
1341
- if ( expr is MethodCallExpression methodCallExpression
1342
+ if ( expr is MethodCallExpression methodCallExpression
1342
1343
&& methodCallExpression . Arguments . Count == 1
1343
1344
&& methodCallExpression . Arguments [ 0 ] is ConstantExpression methodCallExpressionArgument
1344
- && methodCallExpressionArgument . Type == typeof ( string )
1345
+ && methodCallExpressionArgument . Type == typeof ( string )
1345
1346
&& properties . All ( x => x . Name != ( string ) methodCallExpressionArgument . Value ) )
1346
1347
{
1347
1348
propName = ( string ) methodCallExpressionArgument . Value ;
@@ -1516,18 +1517,23 @@ Expression ParseTypeAccess(Type type)
1516
1517
_textParser . NextToken ( ) ;
1517
1518
}
1518
1519
1520
+ Expression generatedExpression = null ;
1521
+
1519
1522
// This is a shorthand for explicitly converting a string to something
1520
1523
bool shorthand = _textParser . CurrentToken . Id == TokenId . StringLiteral ;
1521
1524
if ( _textParser . CurrentToken . Id == TokenId . OpenParen || shorthand )
1522
1525
{
1523
1526
Expression [ ] args = shorthand ? new [ ] { ParseStringLiteral ( ) } : ParseArgumentList ( ) ;
1524
1527
1525
- // If only 1 argument, and the arg is ConstantExpression, return the conversion
1526
- // If only 1 argument, and the arg is null, return the conversion (Can't use constructor)
1527
- if ( args . Length == 1
1528
- && ( args [ 0 ] == null || args [ 0 ] is ConstantExpression ) )
1528
+ // If only 1 argument and
1529
+ // - the arg is ConstantExpression, return the conversion
1530
+ // OR
1531
+ // - the arg is null, return the conversion (Can't use constructor)
1532
+ //
1533
+ // Then try to GenerateConversion
1534
+ if ( args . Length == 1 && ( args [ 0 ] == null || args [ 0 ] is ConstantExpression ) && TryGenerateConversion ( args [ 0 ] , type , out generatedExpression ) )
1529
1535
{
1530
- return GenerateConversion ( args [ 0 ] , type , errorPos ) ;
1536
+ return generatedExpression ;
1531
1537
}
1532
1538
1533
1539
// If only 1 argument, and if the type is a ValueType and argType is also a ValueType, just Convert
@@ -1547,9 +1553,9 @@ Expression ParseTypeAccess(Type type)
1547
1553
switch ( _methodFinder . FindBestMethod ( constructorsWithOutPointerArguments , ref args , out MethodBase method ) )
1548
1554
{
1549
1555
case 0 :
1550
- if ( args . Length == 1 )
1556
+ if ( args . Length == 1 && TryGenerateConversion ( args [ 0 ] , type , out generatedExpression ) )
1551
1557
{
1552
- return GenerateConversion ( args [ 0 ] , type , errorPos ) ;
1558
+ return generatedExpression ;
1553
1559
}
1554
1560
1555
1561
throw ParseError ( errorPos , Res . NoMatchingConstructor , TypeHelper . GetTypeName ( type ) ) ;
@@ -1562,59 +1568,68 @@ Expression ParseTypeAccess(Type type)
1562
1568
}
1563
1569
}
1564
1570
1571
+ // throw ParseError(errorPos, Res.CannotConvertValue, TypeHelper.GetTypeName(exprType), TypeHelper.GetTypeName(type));
1572
+
1565
1573
_textParser . ValidateToken ( TokenId . Dot , Res . DotOrOpenParenOrStringLiteralExpected ) ;
1566
1574
_textParser . NextToken ( ) ;
1567
1575
1568
1576
return ParseMemberAccess ( type , null ) ;
1569
1577
}
1570
1578
1571
- private Expression GenerateConversion ( Expression expr , Type type , int errorPos )
1579
+ private bool TryGenerateConversion ( Expression sourceExpression , Type type , out Expression expression )
1572
1580
{
1573
- Type exprType = expr . Type ;
1581
+ Type exprType = sourceExpression . Type ;
1574
1582
if ( exprType == type )
1575
1583
{
1576
- return expr ;
1584
+ expression = sourceExpression ;
1585
+ return true ;
1577
1586
}
1578
1587
1579
1588
if ( exprType . GetTypeInfo ( ) . IsValueType && type . GetTypeInfo ( ) . IsValueType )
1580
1589
{
1581
1590
if ( ( TypeHelper . IsNullableType ( exprType ) || TypeHelper . IsNullableType ( type ) ) && TypeHelper . GetNonNullableType ( exprType ) == TypeHelper . GetNonNullableType ( type ) )
1582
1591
{
1583
- return Expression . Convert ( expr , type ) ;
1592
+ expression = Expression . Convert ( sourceExpression , type ) ;
1593
+ return true ;
1584
1594
}
1585
1595
1586
1596
if ( ( TypeHelper . IsNumericType ( exprType ) || TypeHelper . IsEnumType ( exprType ) ) && TypeHelper . IsNumericType ( type ) || TypeHelper . IsEnumType ( type ) )
1587
1597
{
1588
- return Expression . ConvertChecked ( expr , type ) ;
1598
+ expression = Expression . ConvertChecked ( sourceExpression , type ) ;
1599
+ return true ;
1589
1600
}
1590
1601
}
1591
1602
1592
1603
if ( exprType . IsAssignableFrom ( type ) || type . IsAssignableFrom ( exprType ) || exprType . GetTypeInfo ( ) . IsInterface || type . GetTypeInfo ( ) . IsInterface )
1593
1604
{
1594
- return Expression . Convert ( expr , type ) ;
1605
+ expression = Expression . Convert ( sourceExpression , type ) ;
1606
+ return true ;
1595
1607
}
1596
1608
1597
1609
// Try to Parse the string rather than just generate the convert statement
1598
- if ( expr . NodeType == ExpressionType . Constant && exprType == typeof ( string ) )
1610
+ if ( sourceExpression . NodeType == ExpressionType . Constant && exprType == typeof ( string ) )
1599
1611
{
1600
- string text = ( string ) ( ( ConstantExpression ) expr ) . Value ;
1612
+ string text = ( string ) ( ( ConstantExpression ) sourceExpression ) . Value ;
1601
1613
1602
1614
var typeConvertor = _typeConverterFactory . GetConverter ( type ) ;
1603
- if ( typeConvertor != null )
1615
+ if ( typeConvertor != null && typeConvertor . CanConvertFrom ( typeof ( string ) ) )
1604
1616
{
1605
1617
var value = typeConvertor . ConvertFromInvariantString ( text ) ;
1606
- return Expression . Constant ( value , type ) ;
1618
+ expression = Expression . Constant ( value , type ) ;
1619
+ return true ;
1607
1620
}
1608
1621
}
1609
1622
1610
1623
// Check if there are any explicit conversion operators on the source type which fit the requirement (cast to the return type).
1611
1624
bool explicitOperatorAvailable = exprType . GetTypeInfo ( ) . GetDeclaredMethods ( "op_Explicit" ) . Any ( m => m . ReturnType == type ) ;
1612
1625
if ( explicitOperatorAvailable )
1613
1626
{
1614
- return Expression . Convert ( expr , type ) ;
1627
+ expression = Expression . Convert ( sourceExpression , type ) ;
1628
+ return true ;
1615
1629
}
1616
1630
1617
- throw ParseError ( errorPos , Res . CannotConvertValue , TypeHelper . GetTypeName ( exprType ) , TypeHelper . GetTypeName ( type ) ) ;
1631
+ expression = null ;
1632
+ return false ;
1618
1633
}
1619
1634
1620
1635
Expression ParseMemberAccess ( Type type , Expression instance )
@@ -1685,7 +1700,7 @@ Expression ParseMemberAccess(Type type, Expression instance)
1685
1700
return Expression . MakeIndex ( instance , typeof ( DynamicClass ) . GetProperty ( "Item" ) , new [ ] { Expression . Constant ( id ) } ) ;
1686
1701
}
1687
1702
#endif
1688
- MemberInfo member = FindPropertyOrField ( type , id , instance == null , _parsingConfig ) ;
1703
+ MemberInfo member = FindPropertyOrField ( type , id , instance == null , _parsingConfig ) ;
1689
1704
if ( member is PropertyInfo property )
1690
1705
{
1691
1706
return Expression . Property ( instance , property ) ;
@@ -1695,11 +1710,13 @@ Expression ParseMemberAccess(Type type, Expression instance)
1695
1710
{
1696
1711
return Expression . Field ( instance , field ) ;
1697
1712
}
1713
+
1698
1714
if ( type == typeof ( object ) )
1699
1715
{
1700
1716
var method = typeof ( Dynamic ) . GetMethod ( "DynamicIndex" , BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static ) ;
1701
1717
return Expression . Call ( null , method , instance , Expression . Constant ( id ) ) ;
1702
1718
}
1719
+
1703
1720
if ( ! _parsingConfig . DisableMemberAccessToIndexAccessorFallback && instance != null )
1704
1721
{
1705
1722
MethodInfo indexerMethod = instance . Type . GetMethod ( "get_Item" , new [ ] { typeof ( string ) } ) ;
@@ -1949,7 +1966,7 @@ static bool TryGetMemberName(Expression expression, out string memberName)
1949
1966
{
1950
1967
memberExpression = ( expression as BinaryExpression ) . Left as MemberExpression ;
1951
1968
}
1952
-
1969
+
1953
1970
if ( memberExpression != null )
1954
1971
{
1955
1972
memberName = memberExpression . Member . Name ;
0 commit comments