mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-18 20:08:15 +08:00
update IQueryable provider
This commit is contained in:
95
Extensions/FreeSql.Extensions.Linq/ExprHelper.cs
Normal file
95
Extensions/FreeSql.Extensions.Linq/ExprHelper.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq.Expressions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FreeSql.Extensions.Linq
|
||||
{
|
||||
public static class ExprHelper
|
||||
{
|
||||
public static object GetConstExprValue(this Expression exp)
|
||||
{
|
||||
if (exp.IsParameter()) return null;
|
||||
|
||||
var expStack = new Stack<Expression>();
|
||||
var exp2 = exp;
|
||||
while (true)
|
||||
{
|
||||
switch (exp2?.NodeType)
|
||||
{
|
||||
case ExpressionType.Constant:
|
||||
expStack.Push(exp2);
|
||||
break;
|
||||
case ExpressionType.MemberAccess:
|
||||
expStack.Push(exp2);
|
||||
exp2 = (exp2 as MemberExpression).Expression;
|
||||
if (exp2 == null) break;
|
||||
continue;
|
||||
case ExpressionType.Call:
|
||||
return Expression.Lambda(exp).Compile().DynamicInvoke();
|
||||
case ExpressionType.TypeAs:
|
||||
case ExpressionType.Convert:
|
||||
var oper2 = (exp2 as UnaryExpression).Operand;
|
||||
if (oper2.NodeType == ExpressionType.Parameter)
|
||||
{
|
||||
var oper2Parm = oper2 as ParameterExpression;
|
||||
expStack.Push(exp2.Type.IsAbstract || exp2.Type.IsInterface ? oper2Parm : Expression.Parameter(exp2.Type, oper2Parm.Name));
|
||||
}
|
||||
else
|
||||
expStack.Push(oper2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
object firstValue = null;
|
||||
switch (expStack.First().NodeType)
|
||||
{
|
||||
case ExpressionType.Constant:
|
||||
var expStackFirst = expStack.Pop() as ConstantExpression;
|
||||
firstValue = expStackFirst?.Value;
|
||||
break;
|
||||
case ExpressionType.MemberAccess:
|
||||
var expStackFirstMem = expStack.First() as MemberExpression;
|
||||
if (expStackFirstMem.Expression?.NodeType == ExpressionType.Constant)
|
||||
firstValue = (expStackFirstMem.Expression as ConstantExpression)?.Value;
|
||||
else
|
||||
return Expression.Lambda(exp).Compile().DynamicInvoke();
|
||||
break;
|
||||
}
|
||||
while (expStack.Any())
|
||||
{
|
||||
var expStackItem = expStack.Pop();
|
||||
switch (expStackItem.NodeType)
|
||||
{
|
||||
case ExpressionType.MemberAccess:
|
||||
var memExp = expStackItem as MemberExpression;
|
||||
if (memExp.Member.MemberType == MemberTypes.Property)
|
||||
firstValue = ((PropertyInfo)memExp.Member).GetValue(firstValue, null);
|
||||
else if (memExp.Member.MemberType == MemberTypes.Field)
|
||||
firstValue = ((FieldInfo)memExp.Member).GetValue(firstValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return firstValue;
|
||||
}
|
||||
|
||||
public static bool IsParameter(this Expression exp)
|
||||
{
|
||||
var test = new TestParameterExpressionVisitor();
|
||||
test.Visit(exp);
|
||||
return test.Result;
|
||||
}
|
||||
internal class TestParameterExpressionVisitor : ExpressionVisitor
|
||||
{
|
||||
public bool Result { get; private set; }
|
||||
|
||||
protected override Expression VisitParameter(ParameterExpression node)
|
||||
{
|
||||
if (!Result) Result = true;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user