Reputation: 10459
How can I convert expression tree to Dictionary?
For example:
class Dummy
{
public int Id { get; set; }
public string Name { get; set; }
}
Example 1:
MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2)
//Result is dictionary with item:
<key, value>Id,2
Example 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"
I know EF Core does this, but don't know how, and source code is to complicated for me to parse it.
I should say expression doesn't contain ||
and ()
.
For example:
MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2 || t.Id == 3)
or
MyStaticClass.ParseExpression<Dummy>(t => t.Id == 2 && (Name == "Foo" || Id Name == "Test")
Upvotes: 1
Views: 272
Reputation: 442
If you are sure that expressions will be in provided format only - you can do something like this:
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;
}
}
Usage:
var test = ExpressionConverter.Convert<Dummy>(x => x.Id == 5 && x.Name == "dummy" && x.Age == 11);
Or replace 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);
}
To support:
var myVar = "dummy";
var test = ExpressionConverter.Convert<Dummy>(x => x.Id == 5 && x.Name == myVar && x.Age == 11);
Upvotes: 2