using Connected.Interop; using System.Linq.Expressions; namespace Connected.Expressions; internal static class ExpressionExtensions { public static Expression Equal(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.Equal(left, right); } public static Expression NotEqual(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.NotEqual(left, right); } public static Expression GreaterThan(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.GreaterThan(left, right); } public static Expression GreaterThanOrEqual(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.GreaterThanOrEqual(left, right); } public static Expression LessThan(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.LessThan(left, right); } public static Expression LessThanOrEqual(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.LessThanOrEqual(left, right); } public static Expression And(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.And(left, right); } public static Expression Or(this Expression left, Expression right) { ConvertExpressions(ref left, ref right); return Expression.Or(left, right); } public static Expression Binary(this Expression left, ExpressionType op, Expression right) { ConvertExpressions(ref left, ref right); return Expression.MakeBinary(op, left, right); } private static void ConvertExpressions(ref Expression left, ref Expression right) { if (left.Type != right.Type) { var isNullable1 = Nullables.IsNullableType(left.Type); var isNullable2 = Nullables.IsNullableType(right.Type); if (isNullable1 || isNullable2) { if (Nullables.GetNonNullableType(left.Type) == Nullables.GetNonNullableType(right.Type)) { if (!isNullable1) left = Expression.Convert(left, right.Type); else if (!isNullable2) right = Expression.Convert(right, left.Type); } } } } public static Expression[] Split(this Expression expression, params ExpressionType[] binarySeparators) { var list = new List(); Split(expression, list, binarySeparators); return list.ToArray(); } private static void Split(Expression expression, List list, ExpressionType[] binarySeparators) { if (expression is not null) { if (binarySeparators.Contains(expression.NodeType)) { if (expression is BinaryExpression bex) { Split(bex.Left, list, binarySeparators); Split(bex.Right, list, binarySeparators); } } else list.Add(expression); } } public static Expression? Join(this IEnumerable list, ExpressionType binarySeparator) { if (list is not null) { var array = list.ToArray(); if (array.Any()) return array.Aggregate((x1, x2) => Expression.MakeBinary(binarySeparator, x1, x2)); } return null; } }