Skip to content

Commit 43842a5

Browse files
committed
Improvements of extension
1 parent fdc2ae2 commit 43842a5

2 files changed

Lines changed: 17 additions & 19 deletions

File tree

Orm/Xtensive.Orm/Linq/ExpressionExtensions.cs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ public static class ExpressionExtensions
2929
private static readonly Func<Type, MethodInfo> TupleValueAccessorFactory;
3030

3131
private static readonly Type MemoryExtensionsType = typeof(MemoryExtensions);
32-
private static readonly MethodInfo ReadOnlySpanContains2;
33-
private static readonly MethodInfo ReadOnlySpanContains3;
34-
private static readonly MethodInfo SpanContains;
32+
33+
private static readonly int[] MemoryExtensionsContainsMethodTokens;
34+
//private static readonly MethodInfo ReadOnlySpanContains2;
35+
//private static readonly MethodInfo ReadOnlySpanContains3;
36+
//private static readonly MethodInfo SpanContains;
3537
private static readonly MethodInfo EnumerableContains;
3638

3739
///<summary>
@@ -89,7 +91,7 @@ public static MethodCallExpression TryTransformToOldFashionContains(this MethodC
8991
{
9092
if (mc.Method.DeclaringType == MemoryExtensionsType) {
9193
var genericMethod = mc.Method.GetGenericMethodDefinition();
92-
if (genericMethod == ReadOnlySpanContains2 || genericMethod == ReadOnlySpanContains3 || genericMethod == SpanContains) {
94+
if (MemoryExtensionsContainsMethodTokens.Contains(genericMethod.MetadataToken)) {
9395
var arguments = mc.Arguments;
9496

9597
Type elementType;
@@ -98,20 +100,20 @@ public static MethodCallExpression TryTransformToOldFashionContains(this MethodC
98100
if (arguments[0] is MethodCallExpression mcInner && mcInner.Method.Name.Equals(WellKnown.Operator.Implicit, StringComparison.Ordinal)) {
99101
var wrappedArray = mcInner.Arguments[0];
100102
elementType = wrappedArray.Type.GetElementType();
101-
newArguments = new[] { wrappedArray, arguments[1] };
103+
newArguments = [wrappedArray, arguments[1]];
102104
}
103105
else if (arguments[0] is UnaryExpression uInner
104106
&& uInner.Method is not null
105107
&& uInner.Method.Name.Equals(WellKnown.Operator.Implicit, StringComparison.Ordinal)) {
106108

107109
elementType = uInner.Operand.Type.GetElementType();
108-
newArguments = new[] { uInner.Operand, arguments[1] };
110+
newArguments = [uInner.Operand, arguments[1]];
109111
}
110112
else {
111113
return mc;
112114
}
113115

114-
var genericContains = EnumerableContains.MakeGenericMethod(elementType);
116+
var genericContains = EnumerableContains.CachedMakeGenericMethod(elementType);
115117
var replacement = Expression.Call(genericContains, newArguments);
116118
return replacement;
117119
}
@@ -135,24 +137,20 @@ static ExpressionExtensions()
135137
var filteredByNameItems = MemoryExtensionsType.GetMethods(BindingFlags.Public | BindingFlags.Static)
136138
.Where(m => m.Name.Equals(nameof(System.MemoryExtensions.Contains), StringComparison.OrdinalIgnoreCase));
137139

138-
var spanCandidates = new List<(MethodInfo, int)>();
139-
var readonlyspanCandidates = new List<(MethodInfo, int)>();
140+
var candiates = new List<int>();
140141

141142
foreach (var method in filteredByNameItems) {
142143
var parameters = method.GetParameters();
143-
var firstParameter = parameters[0];
144-
var genericDef = firstParameter.ParameterType.GetGenericTypeDefinition();
144+
var genericDef = parameters[0].ParameterType.GetGenericTypeDefinition();
145145
if (genericDef == genericReadOnlySpan) {
146-
readonlyspanCandidates.Add((method, parameters.Length));
146+
if (parameters.Length == 2 || parameters.Length==3)
147+
candiates.Add(method.MetadataToken);
147148
}
148-
else if (genericDef == genericSpan) {
149-
spanCandidates.Add((method, parameters.Length));
149+
else if (genericDef == genericSpan && parameters.Length == 2) {
150+
candiates.Add(method.MetadataToken);
150151
}
151152
}
152-
153-
ReadOnlySpanContains2 = readonlyspanCandidates.Where(c => c.Item2 == 2).Select(c => c.Item1).First();
154-
ReadOnlySpanContains3 = readonlyspanCandidates.Where(c => c.Item2 == 3).Select(c => c.Item1).FirstOrDefault();
155-
SpanContains = spanCandidates.Where(c => c.Item2 == 2).Select(c => c.Item1).First();
153+
MemoryExtensionsContainsMethodTokens = candiates.ToArray();
156154
EnumerableContains = typeof(System.Linq.Enumerable).GetMethodEx(nameof(System.Linq.Enumerable.Contains), BindingFlags.Public | BindingFlags.Static, new string[1], new object[2]);
157155
}
158156
}

Orm/Xtensive.Orm/Orm/Providers/Expressions/ExpressionProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ protected override SqlExpression VisitMethodCall(MethodCallExpression mc)
413413
return VisitTupleAccess(mc);
414414

415415
if (mc.Method.Name.Equals(nameof(Enumerable.Contains), StringComparison.Ordinal)) {
416-
// there might be "innovative" implicit cast to ReadOnlySpan inside, which is not supported
416+
// there might be "innovative" implicit cast to ReadOnlySpan inside, which is not supported by expression tree but yet existing
417417
mc = mc.TryTransformToOldFashionContains();
418418
}
419419
var arguments = mc.Arguments.SelectToArray(a => Visit(a));

0 commit comments

Comments
 (0)