解析表达式树

时间:2018-09-21 08:18:26

标签: c# parsing lambda expression

我想使用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)

您能帮我找出我在哪里不正确吗?

1 个答案:

答案 0 :(得分: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变量中获取此类型。希望对您有所帮助。