将 propertyName、条件运算符和值作为 Linq 查询 C# 传递给函数

Passing propertyName, Condition Operator and Value to Function as a Linq query C#

我正在使用 C#,我想以 link 查询的形式将对象的属性传递给函数。条件中比较的 属性、运算符和值应该可供函数使用。

例如

public class Program
{
    public static void Main(string[] args)
    {
       MyMethod(p => p.Age != 23);
    }

    private static void MyMethod( Func<Model,object> parameters)
    {
        //How Do I get the ff
        //PropertyName : "Age"
        //Opertator : "!="
        //Value : 23           
    }
}

public class Model
{
    [Searchable]
    public string Name { get; set; }

    [Searchable]
    public int Age { get; set; }

    [Searchable]
    public DateTime DateOfBirth { get; set; }

    public string Description { get; set; }
}

我真正想做的是像这样调用函数MyMethod(p => (p.Age != 23 , p.Name == "Titan"))。然后访问每个查询的参数名称、运算符和值。我打算将 Mymethod 挂接到 Model(最好只公开具有可搜索属性的属性)。这里的想法是使用 属性 名称、运算符和值来构建一个 sql where 子句。这是我必须实现的想法。除非有更好的方法?

我不知道如何表述这个问题。但我希望它够清楚

也许是这样的:

Expression<Func<Model, bool>> where = p => (p.Age != 23 && p.Name == "Titan");
var result = Models.Where(where);

为了能够分析传递给函数的表达式,您必须使用 Expression class,而不仅仅是 Func<Model, object>。这是您如何分析表达式的草图。显然它只是为了演示目的,你应该根据你的场景调整它(也看看 ExpressionVisitor class 以及如何在这里使用它):

private static void MyMethod(Expression<Func<Model, bool>> parameters) {
    // body is "p.Age != 23"
    var current = parameters.Body;            
    var binary = current as BinaryExpression;
    if (binary == null)
        throw new Exception("Invalid expression");
    // left is "p.Age"
    var left = binary.Left as MemberExpression;
    // right is "23" (constant)
    var right = binary.Right as ConstantExpression;
    if (left != null && right != null) {
        // you can check if Member has Searchable attribute here
        var propertyName = left.Member.Name; // "Age"
        var op = binary.NodeType == ExpressionType.NotEqual ? "!=" : binary.NodeType == ExpressionType.Equal ? "=" : "etc..."; // "!="
        var value = right.Value; // 23
    }
}

用法符合预期:

MyMethod(p => p.Age != 23);
MyMethod(p => p.Name == "Titan");