Skip to content

Optimize GenericExpressionVisitor usage #371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions Orm/Xtensive.Orm/Orm/Linq/Expressions/ConstructorExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ internal sealed class ConstructorExpression : ParameterizedExpression

public override Expression BindParameter(ParameterExpression parameter, Dictionary<Expression, Expression> processedExpressions)
{
Func<Expression, Expression> genericBinder =
e => GenericExpressionVisitor<IMappedExpression>.Process(e, mapped => mapped.BindParameter(parameter, processedExpressions));
GenericExpressionVisitor<IMappedExpression> genericVisitor = new(mapped => mapped.BindParameter(parameter, processedExpressions));
var genericBinder = genericVisitor.Process;
return new ConstructorExpression(
Type,
Bindings.ToDictionary(kvp => kvp.Key, kvp => genericBinder(kvp.Value)),
Expand All @@ -42,8 +42,8 @@ public override Expression BindParameter(ParameterExpression parameter, Dictiona

public override Expression RemoveOuterParameter(Dictionary<Expression, Expression> processedExpressions)
{
Func<Expression, Expression> genericRemover =
e => GenericExpressionVisitor<IMappedExpression>.Process(e, mapped => mapped.RemoveOuterParameter(processedExpressions));
GenericExpressionVisitor<IMappedExpression> genericVisitor = new(mapped => mapped.RemoveOuterParameter(processedExpressions));
var genericRemover = genericVisitor.Process;
var result = new ConstructorExpression(
Type,
Bindings.ToDictionary(kvp => kvp.Key, kvp => genericRemover(kvp.Value)),
Expand All @@ -61,10 +61,10 @@ public override Expression Remap(ColNum offset, Dictionary<Expression, Expressio
return mapped.Remap(offset, new Dictionary<Expression, Expression>());
return (Expression) mapped;
};
var newBindings = Bindings.ToDictionary(kvp => kvp.Key, kvp => GenericExpressionVisitor<IMappedExpression>.Process(kvp.Value, remapper));
var newConstructorArguments = ConstructorArguments
.Select(arg => GenericExpressionVisitor<IMappedExpression>.Process(arg, remapper)).ToArray();
var newNativeBindings = NativeBindings.ToDictionary(kvp => kvp.Key, kvp => GenericExpressionVisitor<IMappedExpression>.Process(kvp.Value, remapper));
GenericExpressionVisitor<IMappedExpression> genericVisitor = new(remapper);
var newBindings = Bindings.ToDictionary(kvp => kvp.Key, kvp => genericVisitor.Process(kvp.Value));
var newConstructorArguments = ConstructorArguments.Select(genericVisitor.Process).ToArray();
var newNativeBindings = NativeBindings.ToDictionary(kvp => kvp.Key, kvp => genericVisitor.Process(kvp.Value));
var result = new ConstructorExpression(
Type,
newBindings,
Expand All @@ -82,9 +82,10 @@ public override Expression Remap(ColumnMap map, Dictionary<Expression, Expressio
return mapped.Remap(map, new Dictionary<Expression, Expression>());
return (Expression) mapped;
};
var newBindings = Bindings.ToDictionary(kvp => kvp.Key, kvp => GenericExpressionVisitor<IMappedExpression>.Process(kvp.Value, remapper));
var newConstructorArguments = ConstructorArguments.Select(arg => GenericExpressionVisitor<IMappedExpression>.Process(arg, remapper)).ToArray();
var newNativeBindings = NativeBindings.ToDictionary(kvp => kvp.Key, kvp => GenericExpressionVisitor<IMappedExpression>.Process(kvp.Value, remapper));
GenericExpressionVisitor<IMappedExpression> genericVisitor = new(remapper);
var newBindings = Bindings.ToDictionary(kvp => kvp.Key, kvp => genericVisitor.Process(kvp.Value));
var newConstructorArguments = ConstructorArguments.Select(genericVisitor.Process).ToArray();
var newNativeBindings = NativeBindings.ToDictionary(kvp => kvp.Key, kvp => genericVisitor.Process(kvp.Value));
return new ConstructorExpression(Type, newBindings, newNativeBindings, Constructor, newConstructorArguments);
}

Expand All @@ -99,4 +100,4 @@ public ConstructorExpression(Type type, Dictionary<MemberInfo, Expression> bindi
Constructor = constructor;
}
}
}
}
5 changes: 2 additions & 3 deletions Orm/Xtensive.Orm/Orm/Linq/Expressions/SubQueryExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ public override SubQueryExpression Remap(ColumnMap map, Dictionary<Expression, E

// Remap Field parametrized parameters
var item = GenericExpressionVisitor<IMappedExpression>.Process(ProjectionExpression.ItemProjector.Item, mapped => {
var parametrizedExpression = mapped as ParameterizedExpression;
if (parametrizedExpression!=null && parametrizedExpression.OuterParameter==OuterParameter)
if (mapped is ParameterizedExpression parametrizedExpression && parametrizedExpression.OuterParameter==OuterParameter)
return mapped.Remap(map, new Dictionary<Expression, Expression>());
return (Expression) mapped;
});
Expand Down Expand Up @@ -133,4 +132,4 @@ public SubQueryExpression(Type type, ParameterExpression parameterExpression, bo
ApplyParameter = applyParameter;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,46 @@
// Created by: Alexis Kochetov
// Created: 2009.05.21

using System;
using System.Linq.Expressions;
using ExpressionVisitor = Xtensive.Linq.ExpressionVisitor;

namespace Xtensive.Orm.Linq.Expressions.Visitors
{
internal sealed class GenericExpressionVisitor<T> : ExpressionVisitor
where T : class
{
private readonly Func<T, Expression> genericProcessor;
namespace Xtensive.Orm.Linq.Expressions.Visitors;

public static Expression Process(Expression target, Func<T, Expression> genericProcessor)
{
var visitor = new GenericExpressionVisitor<T>(genericProcessor);

if (RemapScope.CurrentContext!=null)
return visitor.Visit(target);
internal sealed class GenericExpressionVisitor<T>(Func<T, Expression> genericProcessor) : ExpressionVisitor
where T : class
{
public static Expression Process(Expression target, Func<T, Expression> genericProcessor) =>
new GenericExpressionVisitor<T>(genericProcessor).Process(target);

using (new RemapScope())
return visitor.Visit(target);
}
public Expression Process(Expression target)
{
if (RemapScope.CurrentContext!=null)
return Visit(target);

protected override Expression VisitUnknown(Expression e)
{
var mapped = e as T;
if (mapped!=null)
return VisitGenericExpression(mapped);

var extendedExpression = e as ExtendedExpression;
if (extendedExpression != null && extendedExpression.ExtendedType == ExtendedExpressionType.Marker) {
var marker = (MarkerExpression) e;
var result = Visit(marker.Target);
if (result == marker.Target)
return result;
return new MarkerExpression(result, marker.MarkerType);
}

return base.VisitUnknown(e);
}
using (new RemapScope())
return Visit(target);
}

private Expression VisitGenericExpression(T generic)
{
if (genericProcessor!=null)
return genericProcessor.Invoke(generic);
throw new NotSupportedException(Strings.ExUnableToUseBaseImplementationOfVisitGenericExpressionWithoutSpecifyingGenericProcessorDelegate);
protected override Expression VisitUnknown(Expression e)
{
if (e is T mapped)
return VisitGenericExpression(mapped);

if (e is ExtendedExpression extendedExpression && extendedExpression.ExtendedType == ExtendedExpressionType.Marker) {
var marker = (MarkerExpression) e;
var result = Visit(marker.Target);
if (result == marker.Target)
return result;
return new MarkerExpression(result, marker.MarkerType);
}

return base.VisitUnknown(e);
}

// Constructors

private GenericExpressionVisitor(Func<T, Expression> mappingProcessor)
{
genericProcessor = mappingProcessor;
}
private Expression VisitGenericExpression(T generic)
{
if (genericProcessor!=null)
return genericProcessor.Invoke(generic);
throw new NotSupportedException(Strings.ExUnableToUseBaseImplementationOfVisitGenericExpressionWithoutSpecifyingGenericProcessorDelegate);
}
}
}