C# Expression 树转化为SQL与语句(四)--修正参数本身方法调用的bug

2022/4/11 19:13:38

本文主要是介绍C# Expression 树转化为SQL与语句(四)--修正参数本身方法调用的bug,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace TestExp
{

    public class ExpressionToSql
    {
        public string GetSql<T>(Expression<Func<T, T>> exp)
        {
            return DealExpression(exp.Body);
        }
        public string GetSql<T>(Expression<Func<T, bool>> exp)
        {
            return DealExpression(exp.Body);
        }
        private object Eval(MemberExpression member)
        {
            var cast = Expression.Convert(member, typeof(object));
            object c = Expression.Lambda<Func<object>>(cast).Compile().Invoke();
            return GetValueFormat(c);
        }
        private string DealExpression(Expression exp, bool need = false)
        {
            string name = exp.GetType().Name;
            switch (name)
            {
                case "BinaryExpression":
                case "LogicalBinaryExpression":
                case "MethodBinaryExpression":
                case "SimpleBinaryExpression":
                    {
                        BinaryExpression b_exp = exp as BinaryExpression;
                        if (exp.NodeType == ExpressionType.Add
                            || exp.NodeType == ExpressionType.Subtract
                            //|| exp.NodeType == ExpressionType.Multiply
                            //|| exp.NodeType == ExpressionType.Divide
                            //|| exp.NodeType == ExpressionType.Modulo
                            )
                        {
                            return "(" + DealBinary(b_exp) + ")";
                        }

                        if (!need) return DealBinary(b_exp);
                        BinaryExpression b_left = b_exp.Left as BinaryExpression;
                        BinaryExpression b_right = b_exp.Right as BinaryExpression;
                        if (b_left != null && b_right != null)
                        {
                            return "(" + DealBinary(b_exp) + ")";
                        }
                        return DealBinary(b_exp);
                    }
                case "MemberExpression":
                case "PropertyExpression":
                case "FieldExpression":
                    return DealMember(exp as MemberExpression);
                case "ConstantExpression": return DealConstant(exp as ConstantExpression);
                case "MemberInitExpression":
                    return DealMemberInit(exp as MemberInitExpression);
                case "UnaryExpression": return DealUnary(exp as UnaryExpression);


                case "MethodCallExpressionN":
                    {
                        return DealMethodsCall(exp as MethodCallExpression);
                    }
                case "InstanceMethodCallExpression0":
                    {
                        //// The original expression
                        //Expression<Func<Person1, bool>> expr = (x) => x.Birthday.AddMinutes(1) > DateTime.UtcNow;

                        //// Decompose the original expr.
                        //ParameterExpression param = (ParameterExpression)expr.Parameters[0];
                        //BinaryExpression operation = (BinaryExpression)expr.Body;
                        //var leftExpr = operation.Left;

                        //if (leftExpr is MethodCallExpression)
                        //{
                        //    MethodCallExpression expression = (MethodCallExpression)leftExpr;
                        //    object result = Expression.Lambda(expression, param).Compile().
                        //        DynamicInvoke(new Person1() { Birthday = DateTime.Parse("06-03-2020") });
                        //}
                        //return "";

                        var cast = Expression.Convert(exp, typeof(object));
                        object c = Expression.Lambda<Func<object>>(cast).Compile().Invoke();
                        return GetValueFormat(c);

                    }

                default:
                    Console.WriteLine("error:" + name);

                    return "";
            }

        }
        private string DealFieldAccess(FieldAccessException f_exp)
        {
            var c = f_exp;
            return "";
        }
        private string DealMethodsCall(MethodCallExpression m_exp)
        {
            var k = m_exp;
            var g = k.Arguments[0];
            /// 控制函数所在类名。
            if (k.Method.DeclaringType != typeof(SQLMethods))
            {
                throw new Exception("无法识别函数");
            }
            switch (k.Method.Name)
            {
                case "DB_Length":
                    {
                        var exp = k.Arguments[0];
                        return "LEN(" + DealExpression(exp) + ")";
                    }
                case "DB_In":
                case "DB_NotIn":
                    {
                        var exp1 = k.Arguments[0];
                        var exp2 = k.Arguments[1];
                        string methods = string.Empty;
                        if (k.Method.Name == "In")
                        {
                            methods = " IN ";
                        }
                        else
                        {
                            methods = " NOT IN ";
                        }
                        return DealExpression(exp1) + methods + DealExpression(exp2);
                    }
                case "DB_Like":
                case "DB_NotLike":
                    {
                        var exp1 = k.Arguments[0];
                        var exp2 = k.Arguments[1];
                        string methods = string.Empty;
                        if (k.Method.Name == "DB_Like")
                        {
                            methods = " LIKE ";
                        }
                        else
                        {
                            methods = " NOT LIKE ";
                        }
                        return DealExpression(exp1) + methods + DealExpression(exp2);

                    }
            }
            ///   未知的函数
            throw new Exception("意外的函数");
        }
        private string DealUnary(UnaryExpression u_exp)
        {
            var m = u_exp;
            return DealExpression(u_exp.Operand);

        }
        private string DealMemberInit(MemberInitExpression mi_exp)
        {
            var i = 0;
            string exp_str = string.Empty;
            foreach (var item in mi_exp.Bindings)
            {
                MemberAssignment c = item as MemberAssignment;
                if (i == 0)
                {
                    exp_str += c.Member.Name.ToUpper() + "=" + DealExpression(c.Expression);
                }
                else
                {
                    exp_str += "," + c.Member.Name.ToUpper() + "=" + DealExpression(c.Expression);
                }
                i++;
            }
            return exp_str;

        }
        private string DealBinary(BinaryExpression exp)
        {
            return DealExpression(exp.Left) + NullValueDeal(exp.NodeType, DealExpression(exp.Right, true));// GetOperStr(exp.NodeType) + DealExpression(exp.Right, true);
        }
        private string GetOperStr(ExpressionType e_type)
        {
            switch (e_type)
            {
                case ExpressionType.OrElse: return " OR ";
                case ExpressionType.Or: return "|";
                case ExpressionType.AndAlso: return " AND ";
                case ExpressionType.And: return "&";
                case ExpressionType.GreaterThan: return ">";
                case ExpressionType.GreaterThanOrEqual: return ">=";
                case ExpressionType.LessThan: return "<";
                case ExpressionType.LessThanOrEqual: return "<=";
                case ExpressionType.NotEqual: return "<>";
                case ExpressionType.Add: return "+";
                case ExpressionType.Subtract: return "-";
                case ExpressionType.Multiply: return "*";
                case ExpressionType.Divide: return "/";
                case ExpressionType.Modulo: return "%";
                case ExpressionType.Equal: return "=";
            }
            return "";
        }

        private string DealField(MemberExpression exp)
        {
            return Eval(exp).ToString();
        }
        private string DealMember(MemberExpression exp)
        {
            if (exp.Expression != null)
            {
                if (exp.Expression.GetType().Name == "TypedParameterExpression")
                {
                    return exp.Member.Name;
                }
                return Eval(exp).ToString();

            }


            Type type = exp.Member.ReflectedType;
            PropertyInfo propertyInfo = type.GetProperty(exp.Member.Name, BindingFlags.Static | BindingFlags.Public);
            object o;
            if (propertyInfo != null)
            {
                o = propertyInfo.GetValue(null);
            }
            else
            {
                FieldInfo field = type.GetField(exp.Member.Name, BindingFlags.Static | BindingFlags.Public);
                o = field.GetValue(null);
            }
            return GetValueFormat(o);

        }
        private string DealConstant(ConstantExpression exp)
        {
            var ccc = exp.Value.GetType();

            if (exp.Value == null)
            {
                return "NULL";
            }
            return GetValueFormat(exp.Value);
        }
        private string NullValueDeal(ExpressionType NodeType, string value)
        {
            if (value.ToUpper() != "NULL")
            {
                return GetOperStr(NodeType) + value;
            }

            switch (NodeType)
            {
                case ExpressionType.NotEqual:
                    {
                        return " IS NOT NULL ";
                    }
                case ExpressionType.Equal:
                    {
                        return " IS NULL ";
                    }
                default: return GetOperStr(NodeType) + value;
            }
        }
        private string GetValueFormat(object obj)
        {
            var type = obj.GetType();

            if (type.Name == "List`1") //list集合
            {
                List<string> data = new List<string>();
                var list = obj as IEnumerable;
                string sql = string.Empty;
                foreach (var item in list)
                {
                    data.Add(GetValueFormat(item));
                }
                sql = "(" + string.Join(",", data) + ")";
                return sql;
            }

            if (type == typeof(string))// 
            {
                return string.Format("'{0}'", obj.ToString());
            }
            if (type == typeof(DateTime))
            {
                DateTime dt = (DateTime)obj;
                return string.Format("'{0}'", dt.ToString("yyyy-MM-dd HH:mm:ss fff"));
            }
            return obj.ToString();
        }


    }

    public static class SQLMethods
    {
        public static bool DB_In<T>(this T t, List<T> list)  // in
        {
            return true;
        }
        public static Boolean DB_NotIn<T>(this T t, List<T> list) // not in
        {
            return true;
        }
        public static int DB_Length(this string t)  // len();
        {
            return 0;
        }
        public static bool DB_Like(this string t, string str) // like
        {
            return true;
        }
        public static bool DB_NotLike(this string t, string str) // not like 
        {
            return true;
        }
    }
}

  

 

main函数:

using System.Linq.Expressions;
using System.Reflection;
using TestExp;

class programe
{
    public static void Main(string[] args)
    {
        var v = 500.ToString();

        var con = new ExpressionToSql();
        var sql = con.GetSql<Student>(x => x.name == v.ToString().ToString());

        Console.WriteLine(sql);

        Console.ReadLine();
    }



    public class Student
    {
        public int id { get; set; }
        public string name { get; set; }
        public int math { get; set; } //数学成绩
        public DateTime createTime { get; set; }
    }

}

  



这篇关于C# Expression 树转化为SQL与语句(四)--修正参数本身方法调用的bug的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程