Skip to content

Commit 9517110

Browse files
László Jakabtibitoth
authored andcommitted
Merged PR 14274: Query extensions
+semver: minor Query extensionok a következő feladatokra: - két Expression láncolása - két Expression közötti logikai és/vagy műveletek
2 parents 36ee796 + fa75276 commit 9517110

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using AutSoft.Linq.Expressions.ExpressionVisitors;
2+
3+
using System.Linq.Expressions;
4+
5+
namespace AutSoft.Linq.Expressions;
6+
7+
/// <summary>
8+
/// Extension methods for <see cref="Expression{T}"/> with extended functionality for chaining
9+
/// </summary>
10+
public static class ChainExtension
11+
{
12+
/// <summary>
13+
/// Chaining together two <see cref="Expression{T}"/>
14+
/// </summary>
15+
/// <typeparam name="TIn">Type of input paramter of the result <see cref="Expression{T}"/>'s function</typeparam>
16+
/// <typeparam name="TInterstitial">Type of interstitial parameter of the <see cref="Expression{T}"/> function</typeparam>
17+
/// <typeparam name="TOut">Type of output paramter of the result <see cref="Expression{T}"/>'s function</typeparam>
18+
/// <param name="incomingChainLink">The incoming <see cref="Expression{T}"/> to chaning</param>
19+
/// <param name="outgoingChainLink">The outgoing <see cref="Expression{T}"/> to chaning</param>
20+
/// <returns>The chained together <see cref="Expression{T}"/></returns>
21+
public static Expression<Func<TIn, TOut>> Chain<TIn, TInterstitial, TOut>(
22+
this Expression<Func<TIn, TInterstitial>> incomingChainLink,
23+
Expression<Func<TInterstitial, TOut>> outgoingChainLink)
24+
{
25+
var visitor = new SwapVisitor(outgoingChainLink.Parameters[0], incomingChainLink.Body);
26+
return Expression.Lambda<Func<TIn, TOut>>(visitor.Visit(outgoingChainLink.Body), incomingChainLink.Parameters);
27+
}
28+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Linq.Expressions;
2+
3+
namespace AutSoft.Linq.Expressions.ExpressionVisitors;
4+
5+
/// <summary>
6+
/// An <see cref="ExpressionVisitor"/>, which update a <see cref="ParameterExpression"/>
7+
/// </summary>
8+
internal class ParameterUpdateVisitor : ExpressionVisitor
9+
{
10+
private readonly ParameterExpression _oldParameter;
11+
private readonly ParameterExpression _newParameter;
12+
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="ParameterUpdateVisitor"/> class.
15+
/// </summary>
16+
/// <param name="oldParameter">The <see cref="ParameterExpression"/>, with which identical ones must be replaced</param>
17+
/// <param name="newParameter">The <see cref="ParameterExpression"/>, for which the matches must be exchanged</param>
18+
public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
19+
{
20+
_oldParameter = oldParameter;
21+
_newParameter = newParameter;
22+
}
23+
24+
/// <summary>
25+
/// Visit the <see cref="ParameterExpression"/>
26+
/// </summary>
27+
/// <param name="node">The <see cref="ParameterExpression"/>, that we visit</param>
28+
/// <returns>The <see cref="ParameterExpression"/> after the visit</returns>
29+
protected override Expression VisitParameter(ParameterExpression node)
30+
{
31+
return ReferenceEquals(node, _oldParameter) ? _newParameter : base.VisitParameter(node);
32+
}
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Linq.Expressions;
2+
3+
namespace AutSoft.Linq.Expressions.ExpressionVisitors;
4+
5+
/// <summary>
6+
/// An <see cref="ExpressionVisitor"/>, which swap the visited <see cref="Expression"/> to an other
7+
/// </summary>
8+
internal class SwapVisitor : ExpressionVisitor
9+
{
10+
private readonly Expression _source;
11+
private readonly Expression _replacement;
12+
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="SwapVisitor"/> class.
15+
/// </summary>
16+
/// <param name="source">The <see cref="Expression"/>, with which identical ones must be replaced</param>
17+
/// <param name="replacement">The <see cref="Expression"/>, for which the matches must be exchanged</param>
18+
public SwapVisitor(Expression source, Expression replacement)
19+
{
20+
_source = source;
21+
_replacement = replacement;
22+
}
23+
24+
/// <summary>
25+
/// Visit the <see cref="Expression"/>
26+
/// </summary>
27+
/// <param name="node">The <see cref="Expression"/>, that we visit</param>
28+
/// <returns>The <see cref="Expression"/> after the visit</returns>
29+
public override Expression? Visit(Expression? node)
30+
{
31+
return node == _source ? _replacement : base.Visit(node);
32+
}
33+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using AutSoft.Linq.Expressions.ExpressionVisitors;
2+
3+
using System.Linq.Expressions;
4+
5+
namespace AutSoft.Linq.Expressions;
6+
7+
/// <summary>
8+
/// Extension methods for <see cref="Expression{T}"/> with extended functionality for logical operators
9+
/// </summary>
10+
public static class LogicalOperatorExtensions
11+
{
12+
/// <summary>
13+
/// Performing an AND operation on two <see cref="Expression{T}"/>
14+
/// </summary>
15+
/// <typeparam name="T">Type of input paramter of the <see cref="Expression{T}"/>'s function</typeparam>
16+
/// <param name="leftExp">The left sided <see cref="Expression{T}"/> of AND operation</param>
17+
/// <param name="rightExp">The right sided <see cref="Expression{T}"/> of AND operation</param>
18+
/// <returns>The result <see cref="Expression{T}"/> after the AND operation</returns>
19+
public static Expression<Func<T, bool>> And<T>(
20+
this Expression<Func<T, bool>> leftExp,
21+
Expression<Func<T, bool>> rightExp)
22+
{
23+
var visitor = new ParameterUpdateVisitor(rightExp.Parameters[0], leftExp.Parameters[0]);
24+
rightExp = (Expression<Func<T, bool>>)visitor.Visit(rightExp);
25+
26+
var binExp = Expression.And(leftExp.Body, rightExp.Body);
27+
return Expression.Lambda<Func<T, bool>>(binExp, rightExp.Parameters);
28+
}
29+
30+
/// <summary>
31+
/// Performing an OR operation on two <see cref="Expression{T}"/>
32+
/// </summary>
33+
/// <typeparam name="T">Type of input paramter of the <see cref="Expression{T}"/>'s function</typeparam>
34+
/// <param name="leftExp">The left sided <see cref="Expression{T}"/> of OR operation</param>
35+
/// <param name="rightExp">The right sided <see cref="Expression{T}"/> of OR operation</param>
36+
/// <returns>The result <see cref="Expression{T}"/> after the OR operation</returns>
37+
public static Expression<Func<T, bool>> Or<T>(
38+
this Expression<Func<T, bool>> leftExp,
39+
Expression<Func<T, bool>> rightExp)
40+
{
41+
var visitor = new ParameterUpdateVisitor(rightExp.Parameters[0], leftExp.Parameters[0]);
42+
rightExp = (Expression<Func<T, bool>>)visitor.Visit(rightExp);
43+
44+
var binExp = Expression.Or(leftExp.Body, rightExp.Body);
45+
return Expression.Lambda<Func<T, bool>>(binExp, rightExp.Parameters);
46+
}
47+
}

0 commit comments

Comments
 (0)