Skip to content

Commit 5166df1

Browse files
authored
Process ReadOnlySpan<Key> case (appears with .NET 9.0.200 SDK) (#356)
* Process `ReadOnlySpan<Key>` case (appears with `.NET 9.0.200`) * Update global.json * Substitute `IEnumerable<>.Contains()` instead of `ReadOnlySpan<>`.Contains()
1 parent 7d22884 commit 5166df1

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

Orm/Xtensive.Orm/Orm/Linq/Translator.Queryable.cs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1849,11 +1849,10 @@ private static IReadOnlySet<int> GetNullableGroupingExpressions(IReadOnlyList<(C
18491849
return nullableFields;
18501850
}
18511851

1852-
private bool IsKeyCollection(Type localCollectionType)
1853-
{
1854-
return (localCollectionType.IsArray && localCollectionType.GetElementType() == WellKnownOrmTypes.Key)
1855-
|| IEnumerableOfKeyType.IsAssignableFrom(localCollectionType);
1856-
}
1852+
private bool IsKeyCollection(Type localCollectionType) =>
1853+
(localCollectionType.IsArray && localCollectionType.GetElementType() == WellKnownOrmTypes.Key)
1854+
|| IEnumerableOfKeyType.IsAssignableFrom(localCollectionType)
1855+
|| localCollectionType.IsOfGenericType(WellKnownTypes.ReadOnlySpanOfT) && localCollectionType.GetGenericArguments()[0] == WellKnownOrmTypes.Key;
18571856

18581857
internal void RestoreState(in TranslatorState previousState) =>
18591858
State = previousState;

Orm/Xtensive.Orm/Orm/Linq/WellKnownMembers.cs

+6
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ public static class Enumerable
249249
public static readonly MethodInfo Cast = GetMethod(typeof(System.Linq.Enumerable), nameof(System.Linq.Enumerable.Cast), 1, 1);
250250
}
251251

252+
public static class MemoryExtensions
253+
{
254+
public static readonly MethodInfo ContainsInReadOnlySpan = typeof(System.MemoryExtensions).GetMethods()
255+
.Where(m => m.Name == "Contains" && m.GetParameterTypes()[0].GetGenericTypeDefinition() == WellKnownTypes.ReadOnlySpanOfT).First();
256+
}
257+
252258
// IEntity
253259
public static readonly PropertyInfo IEntityKey = WellKnownOrmInterfaces.Entity.GetProperty(WellKnown.KeyFieldName);
254260
public static readonly PropertyInfo TypeId = WellKnownOrmInterfaces.Entity.GetProperty(WellKnown.TypeIdFieldName);

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ private SqlExpression Visit(Expression e, bool smartNull)
9090
if (evaluator.CanBeEvaluated(e)) {
9191
if (parameterExtractor.IsParameter(e))
9292
return VisitParameterAccess(e, smartNull);
93+
if (e.NodeType == ExpressionType.Call) {
94+
var mc = (MethodCallExpression) e;
95+
var methodDeclaringType = mc.Method.DeclaringType;
96+
if (methodDeclaringType.IsGenericType && methodDeclaringType.GetGenericTypeDefinition() == WellKnownTypes.ReadOnlySpanOfT) {
97+
e = mc.Arguments[0];
98+
}
99+
}
93100
return VisitConstant(ExpressionEvaluator.Evaluate(e));
94101
}
95102
return base.Visit(e);
@@ -410,8 +417,12 @@ protected override SqlExpression VisitMethodCall(MethodCallExpression mc)
410417
var arguments = mc.Arguments.SelectToArray(a => Visit(a));
411418
var mi = mc.Method;
412419

413-
if (mc.Object!=null && mc.Object.Type!=mi.ReflectedType)
420+
if (mc.Object!=null && mc.Object.Type!=mi.ReflectedType) {
414421
mi = mc.Object.Type.GetMethod(mi.Name, mi.GetParameterTypes());
422+
}
423+
else if (mi.IsGenericMethod && mi.GetGenericMethodDefinition() == WellKnownMembers.MemoryExtensions.ContainsInReadOnlySpan) {
424+
mi = WellKnownMembers.Enumerable.Contains.CachedMakeGenericMethod(mi.GetGenericArguments()[0]);
425+
}
415426

416427
return CompileMember(mi, Visit(mc.Object), arguments);
417428
}

global.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"sdk": {
33
"allowPrerelease": true,
4-
"version": "9.0.102",
4+
"version": "9.0.200",
55
"rollForward": "latestMajor"
66
}
77
}

0 commit comments

Comments
 (0)