Force Expression <> to evaluate local variables

I have something like this in LinqPad

 void Main() { var t1 = DateTimeOffset.Parse("10/1/2012"); int? n1 = 1; Expression<Func<Sample,bool>> x1 = ud => (ud.Date == t1 && ud.Number == n1); x1.ToString().Dump(); } class Sample { public int? Number{set;get;} public DateTimeOffset Date{set;get;} } 

displays

ud => ((ud.Date == value (UserQuery + <> c_DisplayClass0) .t1) AndAlso (ud.Number == value (UserQuery + <> c_DisplayClass0) .n1))

Is there any possible way to save the variables, but it outputs something like this:

ud => ((ud.Date == Parse ("10/1/2012")) AndAlso (ud.Number == Conversion (1)))

+4
source share
2 answers

Here we go; first output:

 ud => ((ud.Date == 10/01/2012 00:00:00 +00:00) AndAlso (ud.Number == 1)) 

This will never output Parse(...) , because your expression does not contain parsing: you already appreciated it by the time you entered it in lambda.

Note that this handles one level of the captured variable. For more complex (nested) capture contexts, you will have to recursively extract values ​​from the capture classes:

 using System; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; static class Program { static void Main() { var t1 = DateTimeOffset.Parse("10/1/2012"); int? n1 = 1; Expression<Func<Sample, bool>> x1 = ud => (ud.Date == t1 && ud.Number == n1); var sanitized = (Expression<Func<Sample, bool>>) new Literalizer().Visit(x1); Console.WriteLine(sanitized.ToString()); } } class Literalizer : ExpressionVisitor { protected override Expression VisitMember(MemberExpression node) { if(node.Member.DeclaringType.IsDefined(typeof(CompilerGeneratedAttribute), false) && node.Expression.NodeType == ExpressionType.Constant) { object target = ((ConstantExpression)node.Expression).Value, value; switch (node.Member.MemberType) { case MemberTypes.Property: value = ((PropertyInfo)node.Member).GetValue(target, null); break; case MemberTypes.Field: value = ((FieldInfo)node.Member).GetValue(target); break; default: value = target = null; break; } if (target != null) return Expression.Constant(value, node.Type); } return base.VisitMember(node); } } class Sample { public int? Number{set;get;} public DateTimeOffset Date{set;get;} } 
+7
source

If you agree with the dependence on the details of the implementation of Microsoft.NET Framework / CoreFX, which will be broken in the future, look at the spoiler window below:

Here's the Expression.DebugView property . You will need to do something like search through reflection.
This is implemented using ExpressionVisitor , like what was done at Mark Gravell, answering this question.

Again I want to emphasize this: this is private property.

0
source

Source: https://habr.com/ru/post/1437869/


All Articles