Skip to content

Commit f23e996

Browse files
authored
ParseNumber using CultureInfo from configuration (#323)
* phase 1 * . * { get; set; } * DefaultNumberDecimalSeparator * .
1 parent 57ce8f7 commit f23e996

File tree

8 files changed

+265
-180
lines changed

8 files changed

+265
-180
lines changed

src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public ExpressionParser([CanBeNull] ParameterExpression[] parameters, [NotNull]
8282
_parsingConfig = parsingConfig ?? ParsingConfig.Default;
8383

8484
_keywordsHelper = new KeywordsHelper(_parsingConfig);
85-
_textParser = new TextParser(expression);
85+
_textParser = new TextParser(_parsingConfig, expression);
8686
_methodFinder = new MethodFinder(_parsingConfig);
8787
_expressionHelper = new ExpressionHelper(_parsingConfig);
8888
_typeFinder = new TypeFinder(_parsingConfig, _keywordsHelper);
@@ -843,7 +843,7 @@ Expression ParseIntegerLiteral()
843843
text = text.Substring(2);
844844
}
845845

846-
if (!ulong.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.CurrentCulture, out ulong value))
846+
if (!ulong.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, _parsingConfig.NumberParseCulture, out ulong value))
847847
{
848848
throw ParseError(Res.InvalidIntegerLiteral, text);
849849
}
@@ -872,7 +872,7 @@ Expression ParseIntegerLiteral()
872872
text = text.Substring(3);
873873
}
874874

875-
if (!long.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, CultureInfo.CurrentCulture, out long value))
875+
if (!long.TryParse(text, isHexadecimal ? NumberStyles.HexNumber : NumberStyles.Integer, _parsingConfig.NumberParseCulture, out long value))
876876
{
877877
throw ParseError(Res.InvalidIntegerLiteral, text);
878878
}
@@ -924,7 +924,7 @@ Expression TryParseAsFloat(string text, char qualifier)
924924
{
925925
if (qualifier == 'F' || qualifier == 'f')
926926
{
927-
if (float.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out float f))
927+
if (float.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, _parsingConfig.NumberParseCulture, out float f))
928928
{
929929
return ConstantExpressionHelper.CreateLiteral(f, text);
930930
}
@@ -938,7 +938,7 @@ Expression TryParseAsDecimal(string text, char qualifier)
938938
{
939939
if (qualifier == 'M' || qualifier == 'm')
940940
{
941-
if (decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out decimal d))
941+
if (decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, _parsingConfig.NumberParseCulture, out decimal d))
942942
{
943943
return ConstantExpressionHelper.CreateLiteral(d, text);
944944
}
@@ -953,13 +953,13 @@ Expression TryParseAsDouble(string text, char qualifier)
953953
double d;
954954
if (qualifier == 'D' || qualifier == 'd')
955955
{
956-
if (double.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out d))
956+
if (double.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Number, _parsingConfig.NumberParseCulture, out d))
957957
{
958958
return ConstantExpressionHelper.CreateLiteral(d, text);
959959
}
960960
}
961961

962-
if (double.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out d))
962+
if (double.TryParse(text, NumberStyles.Number, _parsingConfig.NumberParseCulture, out d))
963963
{
964964
return ConstantExpressionHelper.CreateLiteral(d, text);
965965
}

src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs

+18-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ namespace System.Linq.Dynamic.Core.Parser
55
{
66
public class ExpressionPromoter : IExpressionPromoter
77
{
8+
private readonly NumberParser _numberParser;
9+
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="ExpressionPromoter"/> class.
12+
/// </summary>
13+
/// <param name="config">The ParsingConfig.</param>
14+
public ExpressionPromoter(ParsingConfig config)
15+
{
16+
_numberParser = new NumberParser(config);
17+
}
18+
819
/// <inheritdoc cref="IExpressionPromoter.Promote(Expression, Type, bool, bool)"/>
920
public virtual Expression Promote(Expression expr, Type type, bool exact, bool convertExpr)
1021
{
@@ -38,7 +49,7 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c
3849
case TypeCode.UInt32:
3950
case TypeCode.Int64:
4051
case TypeCode.UInt64:
41-
value = TypeHelper.ParseNumber(text, target);
52+
value = _numberParser.ParseNumber(text, target);
4253

4354
// Make sure an enum value stays an enum value
4455
if (target.IsEnum)
@@ -48,32 +59,32 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c
4859
break;
4960

5061
case TypeCode.Double:
51-
if (target == typeof(decimal)) value = TypeHelper.ParseNumber(text, target);
62+
if (target == typeof(decimal)) value = _numberParser.ParseNumber(text, target);
5263
break;
5364

5465
case TypeCode.String:
5566
value = TypeHelper.ParseEnum(text, target);
5667
break;
5768
}
5869
#else
59-
if (ce.Type == typeof(Int32) || ce.Type == typeof(UInt32) || ce.Type == typeof(Int64) || ce.Type == typeof(UInt64))
70+
if (ce.Type == typeof(int) || ce.Type == typeof(uint) || ce.Type == typeof(long) || ce.Type == typeof(ulong))
6071
{
61-
value = TypeHelper.ParseNumber(text, target);
72+
value = _numberParser.ParseNumber(text, target);
6273

6374
// Make sure an enum value stays an enum value
6475
if (target.GetTypeInfo().IsEnum)
6576
{
6677
value = Enum.ToObject(target, value);
6778
}
6879
}
69-
else if (ce.Type == typeof(Double))
80+
else if (ce.Type == typeof(double))
7081
{
7182
if (target == typeof(decimal))
7283
{
73-
value = TypeHelper.ParseNumber(text, target);
84+
value = _numberParser.ParseNumber(text, target);
7485
}
7586
}
76-
else if (ce.Type == typeof(String))
87+
else if (ce.Type == typeof(string))
7788
{
7889
value = TypeHelper.ParseEnum(text, target);
7990
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
namespace System.Linq.Dynamic.Core.Parser
2+
{
3+
/// <summary>
4+
/// NumberParser
5+
/// </summary>
6+
public class NumberParser
7+
{
8+
private readonly ParsingConfig _config;
9+
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="NumberParser"/> class.
12+
/// </summary>
13+
/// <param name="config">The ParsingConfig.</param>
14+
public NumberParser(ParsingConfig config)
15+
{
16+
_config = config;
17+
}
18+
19+
/// <summary>
20+
/// Parses the number (text) into the specified type.
21+
/// </summary>
22+
/// <param name="text">The text.</param>
23+
/// <param name="type">The type.</param>
24+
public object ParseNumber(string text, Type type)
25+
{
26+
try
27+
{
28+
#if !(NETFX_CORE || WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
29+
switch (Type.GetTypeCode(TypeHelper.GetNonNullableType(type)))
30+
{
31+
case TypeCode.SByte:
32+
return sbyte.Parse(text, _config.NumberParseCulture);
33+
case TypeCode.Byte:
34+
return byte.Parse(text, _config.NumberParseCulture);
35+
case TypeCode.Int16:
36+
return short.Parse(text, _config.NumberParseCulture);
37+
case TypeCode.UInt16:
38+
return ushort.Parse(text, _config.NumberParseCulture);
39+
case TypeCode.Int32:
40+
return int.Parse(text, _config.NumberParseCulture);
41+
case TypeCode.UInt32:
42+
return uint.Parse(text, _config.NumberParseCulture);
43+
case TypeCode.Int64:
44+
return long.Parse(text, _config.NumberParseCulture);
45+
case TypeCode.UInt64:
46+
return ulong.Parse(text, _config.NumberParseCulture);
47+
case TypeCode.Single:
48+
return float.Parse(text, _config.NumberParseCulture);
49+
case TypeCode.Double:
50+
return double.Parse(text, _config.NumberParseCulture);
51+
case TypeCode.Decimal:
52+
return decimal.Parse(text, _config.NumberParseCulture);
53+
}
54+
#else
55+
var tp = TypeHelper.GetNonNullableType(type);
56+
if (tp == typeof(sbyte))
57+
{
58+
return sbyte.Parse(text, _config.NumberParseCulture);
59+
}
60+
if (tp == typeof(byte))
61+
{
62+
return byte.Parse(text, _config.NumberParseCulture);
63+
}
64+
if (tp == typeof(short))
65+
{
66+
return short.Parse(text, _config.NumberParseCulture);
67+
}
68+
if (tp == typeof(ushort))
69+
{
70+
return ushort.Parse(text, _config.NumberParseCulture);
71+
}
72+
if (tp == typeof(int))
73+
{
74+
return int.Parse(text, _config.NumberParseCulture);
75+
}
76+
if (tp == typeof(uint))
77+
{
78+
return uint.Parse(text, _config.NumberParseCulture);
79+
}
80+
if (tp == typeof(long))
81+
{
82+
return long.Parse(text, _config.NumberParseCulture);
83+
}
84+
if (tp == typeof(ulong))
85+
{
86+
return ulong.Parse(text, _config.NumberParseCulture);
87+
}
88+
if (tp == typeof(float))
89+
{
90+
return float.Parse(text, _config.NumberParseCulture);
91+
}
92+
if (tp == typeof(double))
93+
{
94+
return double.Parse(text, _config.NumberParseCulture);
95+
}
96+
if (tp == typeof(decimal))
97+
{
98+
return decimal.Parse(text, _config.NumberParseCulture);
99+
}
100+
#endif
101+
}
102+
catch
103+
{
104+
return null;
105+
}
106+
107+
return null;
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)