zspitz / ExpressionTreeToString

String representations of expression trees + library of expression tree objects
MIT License
151 stars 12 forks source link

Dynamic LINQ writer/visitor: Enum handling #63

Closed zspitz closed 4 years ago

zspitz commented 4 years ago

Currently, the following code:

public class Person {
    public DateTime DOB {get; set;}
}
Expression<Func<Person, bool>> expr = p => p.DOB.DayOfWeek == DayOfWeek.Tuesday;
Console.WriteLine(expr.ToString("Dynamic LINQ");

produces:

int(DOB.DayOfWeek) == 2

We have to check for 1. a comparison of 2. a numeric type and 3. an enum value converted to the numeric type. See #25, and https://github.com/zspitz/ExpressionTreeToString/blob/master/Library/CodeWriterVisitors/CodeWriterVisitor.cs#L29.

zspitz commented 4 years ago

Part of this is also how it relates to the in operator. So for the following expression:

Expression<Func<Person, bool>> expr = p => p.DOB.DayOfWeek == DayOfWeek.Tuesday || p.DOB.DayOfWeek == DayOfWeek.Thursday;

which currently produces:

int(DOB.DayOfWeek) == 2 || int(DOB.DayOfWeek) == 4

it should produce:

DOB.DayOfWeek in (DayOfWeek.Tuesday, DayOfWeek.Thursday)

Once we identify int(DOB.DayOfWeek) as a common expression, we can rewrite it as the subject of the in without the conversion. We could then extract the constant value and write the corresponding enum value.

Note that even though some parts of the logic may be shared between WriteBinary above and WriteConditional here, the actual rewriting will have to be done in two separate places.

zspitz commented 4 years ago

RE tests: in addition to the symmetric tests described in https://github.com/zspitz/ExpressionTreeToString/issues/25#issuecomment-722005027, we also need to symmetrically test the in operator:

(Person p) => p.DOB.Day == DayOfWeek.Tuesday || p.DOB.Day == DayOfWeek.Thursday

should convert to:

DOB.Day in (DayOfWeek.Tuesday, DayOfWeek.Thursday)

while:

(Person p) => DayOfWeek.Tuesday == p.DOB.Day || DayOfWeek.Tuesday == p.DateRegistered.Day

should convert to:

DayOfWeek.Tuesday in (DOB.Day, DateRegistered.Day)