-
Notifications
You must be signed in to change notification settings - Fork 186
Expand file tree
/
Copy pathClrCanonicalFunctions.cs
More file actions
180 lines (159 loc) · 11.1 KB
/
Copy pathClrCanonicalFunctions.cs
File metadata and controls
180 lines (159 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//-----------------------------------------------------------------------------
// <copyright file="ClrCanonicalFunctions.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------
// This file isn't generated, but this comment is necessary to exclude it from StyleCop analysis.
// <auto-generated/>
// We use the auto-generated tag to exclude it from code analysis, otherwise, a lot of string related function call
// such as, StartsWith will have the warning.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.OData.Edm;
namespace Microsoft.AspNetCore.OData.Query;
internal class ClrCanonicalFunctions
{
private static string _defaultString = default(string);
private static Enum _defaultEnum = default(Enum);
// function names
internal const string StartswithFunctionName = "startswith";
internal const string EndswithFunctionName = "endswith";
internal const string ContainsFunctionName = "contains";
internal const string SubstringFunctionName = "substring";
internal const string LengthFunctionName = "length";
internal const string IndexofFunctionName = "indexof";
internal const string TolowerFunctionName = "tolower";
internal const string ToupperFunctionName = "toupper";
internal const string TrimFunctionName = "trim";
internal const string ConcatFunctionName = "concat";
internal const string MatchesPatternFunctionName = "matchesPattern";
internal const string YearFunctionName = "year";
internal const string MonthFunctionName = "month";
internal const string DayFunctionName = "day";
internal const string HourFunctionName = "hour";
internal const string MinuteFunctionName = "minute";
internal const string SecondFunctionName = "second";
internal const string MillisecondFunctionName = "millisecond";
internal const string FractionalSecondsFunctionName = "fractionalseconds";
internal const string TotalSecondsFunctionName = "totalseconds";
internal const string RoundFunctionName = "round";
internal const string FloorFunctionName = "floor";
internal const string CeilingFunctionName = "ceiling";
internal const string CastFunctionName = "cast";
internal const string IsofFunctionName = "isof";
internal const string DateFunctionName = "date";
internal const string TimeFunctionName = "time";
internal const string NowFunctionName = "now";
// string functions
public static readonly MethodInfo StartsWith = MethodOf(_ => _defaultString.StartsWith(default(string)));
public static readonly MethodInfo EndsWith = MethodOf(_ => _defaultString.EndsWith(default(string)));
public static readonly MethodInfo Contains = MethodOf(_ => _defaultString.Contains(default(string)));
public static readonly MethodInfo SubstringStart = MethodOf(_ => _defaultString.Substring(default(int)));
public static readonly MethodInfo SubstringStartAndLength = MethodOf(_ => _defaultString.Substring(default(int), default(int)));
public static readonly MethodInfo SubstringStartNoThrow = MethodOf(_ => ClrSafeFunctions.SubstringStart(default(string), default(int)));
public static readonly MethodInfo SubstringStartAndLengthNoThrow = MethodOf(_ => ClrSafeFunctions.SubstringStartAndLength(default(string), default(int), default(int)));
public static readonly MethodInfo IndexOf = MethodOf(_ => _defaultString.IndexOf(default(string)));
public static readonly MethodInfo ToLower = MethodOf(_ => _defaultString.ToLower());
public static readonly MethodInfo ToUpper = MethodOf(_ => _defaultString.ToUpper());
public static readonly MethodInfo Trim = MethodOf(_ => _defaultString.Trim());
public static readonly MethodInfo Concat = MethodOf(_ => String.Concat(default(string), default(string)));
public static readonly MethodInfo MatchesMattern = MethodOf(_ => Regex.IsMatch(default(string), default(string), default(RegexOptions)));
// math functions
public static readonly MethodInfo CeilingOfDouble = MethodOf(_ => Math.Ceiling(default(double)));
public static readonly MethodInfo RoundOfDouble = MethodOf(_ => Math.Round(default(double)));
public static readonly MethodInfo FloorOfDouble = MethodOf(_ => Math.Floor(default(double)));
public static readonly MethodInfo CeilingOfDecimal = MethodOf(_ => Math.Ceiling(default(decimal)));
public static readonly MethodInfo RoundOfDecimal = MethodOf(_ => Math.Round(default(decimal)));
public static readonly MethodInfo FloorOfDecimal = MethodOf(_ => Math.Floor(default(decimal)));
// enum functions
public static readonly MethodInfo HasFlag = MethodOf(_ => _defaultEnum.HasFlag(default(Enum)));
// Date properties
public static readonly Dictionary<string, PropertyInfo> DateProperties = new[]
{
new KeyValuePair<string, PropertyInfo>(YearFunctionName, typeof(Date).GetProperty("Year")),
new KeyValuePair<string, PropertyInfo>(MonthFunctionName, typeof(Date).GetProperty("Month")),
new KeyValuePair<string, PropertyInfo>(DayFunctionName, typeof(Date).GetProperty("Day")),
}.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
// DateTimeproperties
public static readonly Dictionary<string, PropertyInfo> DateTimeProperties = new[]
{
new KeyValuePair<string, PropertyInfo>(YearFunctionName, typeof(DateTime).GetProperty("Year")),
new KeyValuePair<string, PropertyInfo>(MonthFunctionName, typeof(DateTime).GetProperty("Month")),
new KeyValuePair<string, PropertyInfo>(DayFunctionName, typeof(DateTime).GetProperty("Day")),
new KeyValuePair<string, PropertyInfo>(HourFunctionName, typeof(DateTime).GetProperty("Hour")),
new KeyValuePair<string, PropertyInfo>(MinuteFunctionName, typeof(DateTime).GetProperty("Minute")),
new KeyValuePair<string, PropertyInfo>(SecondFunctionName, typeof(DateTime).GetProperty("Second")),
new KeyValuePair<string, PropertyInfo>(MillisecondFunctionName, typeof(DateTime).GetProperty("Millisecond")),
}.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
// DateTimeOffset properties
public static readonly Dictionary<string, PropertyInfo> DateTimeOffsetProperties = new[]
{
new KeyValuePair<string, PropertyInfo>(YearFunctionName, typeof(DateTimeOffset).GetProperty("Year")),
new KeyValuePair<string, PropertyInfo>(MonthFunctionName, typeof(DateTimeOffset).GetProperty("Month")),
new KeyValuePair<string, PropertyInfo>(DayFunctionName, typeof(DateTimeOffset).GetProperty("Day")),
new KeyValuePair<string, PropertyInfo>(HourFunctionName, typeof(DateTimeOffset).GetProperty("Hour")),
new KeyValuePair<string, PropertyInfo>(MinuteFunctionName, typeof(DateTimeOffset).GetProperty("Minute")),
new KeyValuePair<string, PropertyInfo>(SecondFunctionName, typeof(DateTimeOffset).GetProperty("Second")),
new KeyValuePair<string, PropertyInfo>(MillisecondFunctionName, typeof(DateTimeOffset).GetProperty("Millisecond")),
}.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
// TimeOfDay properties
// ODL uses the Hour(s), Minute(s), Second(s), It's the wrong property name. It should be Hour, Minute, Second.
public static readonly Dictionary<string, PropertyInfo> TimeOfDayProperties = new[]
{
new KeyValuePair<string, PropertyInfo>(HourFunctionName, typeof(TimeOfDay).GetProperty("Hours")),
new KeyValuePair<string, PropertyInfo>(MinuteFunctionName, typeof(TimeOfDay).GetProperty("Minutes")),
new KeyValuePair<string, PropertyInfo>(SecondFunctionName, typeof(TimeOfDay).GetProperty("Seconds")),
new KeyValuePair<string, PropertyInfo>(MillisecondFunctionName, typeof(TimeOfDay).GetProperty("Milliseconds")),
}.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
// DateOnly properties
public static readonly Dictionary<string, PropertyInfo> DateOnlyProperties = new Dictionary<string, PropertyInfo>
{
{ YearFunctionName, typeof(DateOnly).GetProperty(nameof(DateOnly.Year)) },
{ MonthFunctionName, typeof(DateOnly).GetProperty(nameof(DateOnly.Month)) },
{ DayFunctionName, typeof(DateOnly).GetProperty(nameof(DateOnly.Day)) }
};
// TimeOnly properties
public static readonly Dictionary<string, PropertyInfo> TimeOnlyProperties = new Dictionary<string, PropertyInfo>
{
{ HourFunctionName, typeof(TimeOnly).GetProperty(nameof(TimeOnly.Hour)) },
{ MinuteFunctionName, typeof(TimeOnly).GetProperty(nameof(TimeOnly.Minute)) },
{ SecondFunctionName, typeof(TimeOnly).GetProperty(nameof(TimeOnly.Second)) },
{ MillisecondFunctionName, typeof(TimeOnly).GetProperty(nameof(TimeOnly.Millisecond)) }
};
// TimeSpan properties
public static readonly Dictionary<string, PropertyInfo> TimeSpanProperties = new[]
{
new KeyValuePair<string, PropertyInfo>(HourFunctionName, typeof(TimeSpan).GetProperty("Hours")),
new KeyValuePair<string, PropertyInfo>(MinuteFunctionName, typeof(TimeSpan).GetProperty("Minutes")),
new KeyValuePair<string, PropertyInfo>(SecondFunctionName, typeof(TimeSpan).GetProperty("Seconds")),
new KeyValuePair<string, PropertyInfo>(MillisecondFunctionName, typeof(TimeSpan).GetProperty("Milliseconds")),
}.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
// TimeSpan/Duration "total" property used by the OData V4 totalseconds() canonical function.
public static readonly PropertyInfo TimeSpanTotalSeconds = typeof(TimeSpan).GetProperty(nameof(TimeSpan.TotalSeconds));
// String Properties
public static readonly PropertyInfo Length = typeof(string).GetProperty("Length");
// PropertyInfo and MethodInfo of DateTime & DateTimeOffset related.
public static readonly PropertyInfo DateTimeKindPropertyInfo = typeof(DateTime).GetProperty("Kind");
public static readonly MethodInfo ToUniversalTimeDateTime = typeof(DateTime).GetMethod("ToUniversalTime", BindingFlags.Instance | BindingFlags.Public);
public static readonly MethodInfo ToUniversalTimeDateTimeOffset = typeof(DateTimeOffset).GetMethod("ToUniversalTime", BindingFlags.Instance | BindingFlags.Public);
public static readonly MethodInfo ToOffsetFunction = typeof(DateTimeOffset).GetMethod("ToOffset", BindingFlags.Instance | BindingFlags.Public);
public static readonly MethodInfo GetUtcOffset = typeof(TimeZoneInfo).GetMethod("GetUtcOffset", new[] { typeof(DateTime) });
private static MethodInfo MethodOf<TReturn>(Expression<Func<object, TReturn>> expression)
{
return MethodOf(expression as Expression);
}
private static MethodInfo MethodOf(Expression expression)
{
LambdaExpression lambdaExpression = expression as LambdaExpression;
Contract.Assert(lambdaExpression != null);
Contract.Assert(expression.NodeType == ExpressionType.Lambda);
Contract.Assert(lambdaExpression.Body.NodeType == ExpressionType.Call);
return (lambdaExpression.Body as MethodCallExpression).Method;
}
}