将表达式树转换为字典

时间:2019-02-14 07:58:36

标签: c#

如何将表达式树转换为字典?

例如:

class Dummy
{
    public int Id { get; set; }
    public string Name { get; set; }
}

示例1:

MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2)

//Result is dictionary with item: 
    <key, value>Id,2

示例2:

var s = "Foo";
MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2 && t.Name == s)

//Result is dictionary with items:
    <key, value>Id,2
    <key, value>Name,"Foo"

我知道EF Core可以做到这一点,但不知道如何实现,因此我难以解析源代码。

我应该说表达式不包含||()
例如:

MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2 || t.Id == 3)

MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2 && (Name == "Foo" || Id Name == "Test")

1 个答案:

答案 0 :(得分:2)

如果您确定表达式将仅采用提供的格式-您可以执行以下操作:

public class Dummy
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

public class ExpressionConverter
{
    public static Dictionary<string, string> Convert<T>(Expression<Func<T,bool>> expression)
    {
        var result = new Dictionary<string,string>();

        var current = (BinaryExpression)expression.Body;

        while (current.NodeType != ExpressionType.Equal)
        {
            ParseEquals((BinaryExpression)current.Right);
            current = (BinaryExpression)current.Left;
        }

        ParseEquals(current);

        void ParseEquals(BinaryExpression e)
        {
            var key = (MemberExpression) e.Left;
            var value = (ConstantExpression) e.Right;
            result.Add(key.Member.Name, value.Value.ToString());
        }

        return result;
    }
}

用法

var test = ExpressionConverter.Convert<Dummy>(x => x.Id == 5 && x.Name == "dummy" && x.Age == 11);

或替换ParseEquals

void ParseEquals(BinaryExpression e)
{
    var key = (MemberExpression) e.Left;
    object value;
    switch (e.Right)
    {
        case ConstantExpression constantExpression:
            value = constantExpression.Value;
            break;
        case MemberExpression memberExpression:
            var obj = ((ConstantExpression)memberExpression.Expression).Value;
            value = obj.GetType().GetField(memberExpression.Member.Name).GetValue(obj);
            break;
        default:
            throw new UnknownSwitchValueException(e.Right.Type);
    }
    result.Add(key.Member.Name, value);
}

支持:

var myVar = "dummy";
var test = ExpressionConverter.Convert<Dummy>(x => x.Id == 5 && x.Name == myVar && x.Age == 11);