Skip to content

Commit 5fedf24

Browse files
committed
Optimize AllocateParameterAndReplacer()
1 parent ce33c5e commit 5fedf24

File tree

2 files changed

+26
-35
lines changed

2 files changed

+26
-35
lines changed

Orm/Xtensive.Orm/Orm/Internals/CompiledQueryRunner.cs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -159,40 +159,43 @@ private void AllocateParameterAndReplacer()
159159
var closureType = queryTarget.GetType();
160160
var parameterType = WellKnownOrmTypes.ParameterOfT.CachedMakeGenericType(closureType);
161161
var valueMemberInfo = parameterType.GetProperty(nameof(Parameter<object>.Value), closureType);
162+
MemberExpression closureAccessor = null;
162163
queryParameter = (Parameter) System.Activator.CreateInstance(parameterType, "pClosure");
164+
bool? closureTypeIsClosure = null;
165+
FieldInfo[] closureTypeFields = null;
163166
queryParameterReplacer = new ExtendedExpressionReplacer(expression => {
164167
if (expression.NodeType == ExpressionType.Constant) {
165-
if ((expression as ConstantExpression).Value == null) {
166-
return null;
167-
}
168-
if (expression.Type.IsClosure()) {
169-
if (expression.Type==closureType) {
170-
return Expression.MakeMemberAccess(Expression.Constant(queryParameter, parameterType), valueMemberInfo);
171-
}
172-
else {
173-
throw new NotSupportedException(string.Format(
174-
Strings.ExExpressionDefinedOutsideOfCachingQueryClosure, expression));
175-
}
168+
if (((ConstantExpression)expression).Value is null) {
169+
return null;
176170
}
177171

178-
if (closureType.DeclaringType==null) {
179-
if (expression.Type.IsAssignableFrom(closureType))
180-
return Expression.MakeMemberAccess(Expression.Constant(queryParameter, parameterType), valueMemberInfo);
172+
var expressionType = expression.Type;
173+
if (expressionType.IsClosure()) {
174+
return expressionType == closureType
175+
? GetClosureAccessor()
176+
: throw new NotSupportedException(string.Format(Strings.ExExpressionDefinedOutsideOfCachingQueryClosure, expression));
181177
}
182-
else {
183-
if (expression.Type.IsAssignableFrom(closureType))
184-
return Expression.MakeMemberAccess(Expression.Constant(queryParameter, parameterType), valueMemberInfo);
185-
if (expression.Type.IsAssignableFrom(closureType.DeclaringType)) {
186-
var memberInfo = closureType.TryGetFieldInfoFromClosure(expression.Type);
187-
if (memberInfo != null)
188-
return Expression.MakeMemberAccess(
189-
Expression.MakeMemberAccess(Expression.Constant(queryParameter, parameterType), valueMemberInfo),
190-
memberInfo);
178+
179+
if (expressionType.IsAssignableFrom(closureType))
180+
return GetClosureAccessor();
181+
if (closureType.DeclaringType is { } closureTypeDeclaringType && expressionType.IsAssignableFrom(closureTypeDeclaringType)) {
182+
if (closureTypeIsClosure is null) {
183+
closureTypeIsClosure = closureType.IsClosure();
184+
closureTypeFields = closureTypeIsClosure.Value ? closureType.GetFields() : null;
185+
}
186+
187+
if (closureTypeIsClosure.Value
188+
&& closureTypeFields.FirstOrDefault(field => field.FieldType == expressionType) is { } memberInfo) {
189+
return Expression.MakeMemberAccess(GetClosureAccessor(), memberInfo);
191190
}
192191
}
193192
}
193+
194194
return null;
195195
});
196+
197+
MemberExpression GetClosureAccessor() =>
198+
closureAccessor ??= Expression.MakeMemberAccess(Expression.Constant(queryParameter, parameterType), valueMemberInfo);
196199
}
197200

198201
private ParameterizedQuery GetCachedQuery() =>

Orm/Xtensive.Orm/Reflection/TypeHelper.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,18 +1261,6 @@ internal static bool IsValueTuple(this Type type)
12611261

12621262
#region Private \ internal methods
12631263

1264-
/// <summary>
1265-
/// Gets information about field in closure.
1266-
/// </summary>
1267-
/// <param name="closureType">Closure type.</param>
1268-
/// <param name="fieldType">Type of field in closure.</param>
1269-
/// <returns>If field of <paramref name="fieldType"/> exists in closure then returns
1270-
/// <see cref="MemberInfo"/> of that field, otherwise, <see langword="null"/>.</returns>
1271-
internal static MemberInfo TryGetFieldInfoFromClosure(this Type closureType, Type fieldType) =>
1272-
closureType.IsClosure()
1273-
? closureType.GetFields().FirstOrDefault(field => field.FieldType == fieldType)
1274-
: null;
1275-
12761264
private static string TrimGenericSuffix(string @string)
12771265
{
12781266
var backtickPosition = @string.IndexOf('`');

0 commit comments

Comments
 (0)