145 lines
4.4 KiB
C#
145 lines
4.4 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Linq.Expressions;
|
|||
|
|
using System.Reflection;
|
|||
|
|
|
|||
|
|
namespace Hncore.Infrastructure.EntitiesExtension
|
|||
|
|
{
|
|||
|
|
internal class ConditionBuilder : ExpressionVisitor
|
|||
|
|
{
|
|||
|
|
private List<object> m_arguments;
|
|||
|
|
private Stack<string> m_conditionParts;
|
|||
|
|
|
|||
|
|
public string Condition { get; private set; }
|
|||
|
|
|
|||
|
|
public object[] Arguments { get; private set; }
|
|||
|
|
|
|||
|
|
public void Build(Expression expression)
|
|||
|
|
{
|
|||
|
|
PartialEvaluator evaluator = new PartialEvaluator();
|
|||
|
|
Expression evaluatedExpression = evaluator.Eval(expression);
|
|||
|
|
|
|||
|
|
this.m_arguments = new List<object>();
|
|||
|
|
this.m_conditionParts = new Stack<string>();
|
|||
|
|
|
|||
|
|
this.Visit(evaluatedExpression);
|
|||
|
|
|
|||
|
|
this.Arguments = this.m_arguments.ToArray();
|
|||
|
|
this.Condition = this.m_conditionParts.Count > 0 ? this.m_conditionParts.Pop() : null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override Expression VisitBinary(BinaryExpression b)
|
|||
|
|
{
|
|||
|
|
if (b == null) return b;
|
|||
|
|
|
|||
|
|
string opr;
|
|||
|
|
switch (b.NodeType)
|
|||
|
|
{
|
|||
|
|
case ExpressionType.Equal:
|
|||
|
|
opr = "=";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.NotEqual:
|
|||
|
|
opr = "<>";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.GreaterThan:
|
|||
|
|
opr = ">";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.GreaterThanOrEqual:
|
|||
|
|
opr = ">=";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.LessThan:
|
|||
|
|
opr = "<";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.LessThanOrEqual:
|
|||
|
|
opr = "<=";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.AndAlso:
|
|||
|
|
opr = "AND";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.OrElse:
|
|||
|
|
opr = "OR";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.Add:
|
|||
|
|
opr = "+";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.Subtract:
|
|||
|
|
opr = "-";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.Multiply:
|
|||
|
|
opr = "*";
|
|||
|
|
break;
|
|||
|
|
case ExpressionType.Divide:
|
|||
|
|
opr = "/";
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
throw new NotSupportedException(b.NodeType + "is not supported.");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.Visit(b.Left);
|
|||
|
|
this.Visit(b.Right);
|
|||
|
|
|
|||
|
|
string right = this.m_conditionParts.Pop();
|
|||
|
|
string left = this.m_conditionParts.Pop();
|
|||
|
|
|
|||
|
|
string condition = String.Format("({0} {1} {2})", left, opr, right);
|
|||
|
|
this.m_conditionParts.Push(condition);
|
|||
|
|
|
|||
|
|
return b;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override Expression VisitConstant(ConstantExpression c)
|
|||
|
|
{
|
|||
|
|
if (c == null) return c;
|
|||
|
|
|
|||
|
|
this.m_arguments.Add(c.Value);
|
|||
|
|
this.m_conditionParts.Push(String.Format("{{{0}}}", this.m_arguments.Count - 1));
|
|||
|
|
|
|||
|
|
return c;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override Expression VisitMemberAccess(MemberExpression m)
|
|||
|
|
{
|
|||
|
|
if (m == null) return m;
|
|||
|
|
|
|||
|
|
PropertyInfo propertyInfo = m.Member as PropertyInfo;
|
|||
|
|
if (propertyInfo == null) return m;
|
|||
|
|
|
|||
|
|
this.m_conditionParts.Push(String.Format("[{0}]", propertyInfo.Name));
|
|||
|
|
|
|||
|
|
return m;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
protected override Expression VisitMethodCall(MethodCallExpression m)
|
|||
|
|
{
|
|||
|
|
if (m == null) return m;
|
|||
|
|
|
|||
|
|
string format;
|
|||
|
|
switch (m.Method.Name)
|
|||
|
|
{
|
|||
|
|
case "StartsWith":
|
|||
|
|
format = "({0} LIKE {1}+'%')";
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case "Contains":
|
|||
|
|
format = "({0} LIKE '%'+{1}+'%')";
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case "EndsWith":
|
|||
|
|
format = "({0} LIKE '%'+{1})";
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
throw new NotSupportedException(m.NodeType + " is not supported!");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.Visit(m.Object);
|
|||
|
|
this.Visit(m.Arguments[0]);
|
|||
|
|
string right = this.m_conditionParts.Pop();
|
|||
|
|
string left = this.m_conditionParts.Pop();
|
|||
|
|
this.m_conditionParts.Push(String.Format(format, left, right));
|
|||
|
|
|
|||
|
|
return m;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|