【问题标题】:Parsing Expression Tree解析表达式树
【发布时间】:2018-09-21 16:59:12
【问题描述】:

我想使用 LINQ 表达式作为方法参数来构建 Dapper 字符串。我在 MS Docs 中找到了一个解析示例并将其集成到我的代码中:

public static List<Notification> GetNotifs(Expression<Func<Notification, bool>> p)
        {
            using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
            {
                string sqlQ = "SELECT * FROM Notifications WHERE ";
                ParameterExpression param = p.Parameters[0];
                BinaryExpression operation = (BinaryExpression)p.Body;
                ParameterExpression left = (ParameterExpression)operation.Left;
                for (int i = 0; i < left.Name.Length; i++) { if (i <= param.Name.Length) { } else { sqlQ += left.Name[i]; } }
                ConstantExpression right = (ConstantExpression)operation.Right;
                if (operation.NodeType.ToString() == "LessThan") sqlQ += " <";
                else if (operation.NodeType.ToString() == "GreaterThan") sqlQ += " >";
                else if (operation.NodeType.ToString() == "LessThanOrEqual") sqlQ += " <=";
                else if (operation.NodeType.ToString() == "GreaterThanOrEqual") sqlQ += " >=";
                else if (operation.NodeType.ToString() == "Equal") sqlQ += " =";
                else if (operation.NodeType.ToString() == "NotEqual") sqlQ += " !=";
                sqlQ += " " + right.Value;
                return connection.Query<Notification>(sqlQ).ToList();
            }
        }

但是,不幸的是它在

处给出了一个 InvalidCastException
ParameterExpression left = (ParameterExpression)operation.Left;

这个方法的调用是这样的:

DRepository.GetNotifs(uid => uid.U_Id == id)

你能帮我看看,我哪里错了吗?

【问题讨论】:

    标签: c# parsing lambda expression


    【解决方案1】:

    以下示例生成 SQL SELECT * FROM Notifications WHERE U_Id = 1:

    [Test]
    public void DapperExpression()
    {
        // Arrange
        var id = 1;
    
        // Act
        var list = GetNotifs(uid => uid.U_Id == id);
    
        // Assert 
        Assert.IsNotEmpty(list);
    }
    
    public static List<Notification> GetNotifs(Expression<Func<Notification, bool>> p)
    {
        using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
        {
            string sqlQ = "SELECT * FROM Notifications WHERE ";
            ParameterExpression param = p.Parameters[0];
            BinaryExpression operation = (BinaryExpression)p.Body;
            var t = operation.Left.GetType();
            MemberExpression left = (MemberExpression)operation.Left;
            sqlQ += left.Member.Name;
            MemberExpression right = (MemberExpression)operation.Right;
            ConstantExpression cnst = (ConstantExpression) right.Expression;
            var field = cnst.Type.GetFields().Single();
            var val = field.GetValue(cnst.Value);
    
            if (operation.NodeType.ToString() == "LessThan") sqlQ += " <";
            else if (operation.NodeType.ToString() == "GreaterThan") sqlQ += " >";
            else if (operation.NodeType.ToString() == "LessThanOrEqual") sqlQ += " <=";
            else if (operation.NodeType.ToString() == "GreaterThanOrEqual") sqlQ += " >=";
            else if (operation.NodeType.ToString() == "Equal") sqlQ += " =";
            else if (operation.NodeType.ToString() == "NotEqual") sqlQ += " !=";
            sqlQ += " " + val;
    
            return connection.Query<Notification>(sqlQ).ToList();
        }
    }
    

    请注意,它适用于int。例如,您应该添加一些类型相关的逻辑来为 stringGuid 添加引用。您可以从field 变量中获取此类型。希望对您有所帮助。

    【讨论】:

    • 我会尝试找出它(关于类型)。非常感谢。
    • 乐于助人=)
    猜你喜欢
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多