Below is a simple demo code of my problem.
[TestClass] public class ExpressionTests { [TestMethod] public void TestParam() { Search<Student>(s => s.Id == 1L); GetStudent(1L); } private void GetStudent(long id) { Search<Student>(s => s.Id == id); } private void Search<T>(Expression<Func<T, bool>> filter) { var visitor = new MyExpressionVisitor(); visitor.Visit(filter); } } public class MyExpressionVisitor : ExpressionVisitor { protected override Expression VisitConstant(ConstantExpression node) { Assert.AreEqual(1L, node.Value); return base.VisitConstant(node); } }
TestParam calls VisitConstant on two different paths:
1. TestParam β Search β VisitConstant
In this execution path, the constant expression (1L) passed to the Search method is a real constant value. Everything is in order here, the statement succeeds as expected. When VisitConstant is called through the first path, node.Value.GetType() is Int64 and its .Value is 1L .
2. TestParam β GetStudent β Search β VisitConstant
In this expression, the execution path constant (id: 1L) is taken as an argument to GetStudent and passed to the Search method inside the closure.
Problem
The problem is the second way of execution. When VisitConstant is called via the second path node.Value.GetType() is MyProject.Tests.ExpressionTests+<>c__DisplayClass0 , and this class has a public field called id (the same as the argument of the GetStudent method), which has a value of 1L .
Question
How can I get the id value in the second path? I know about closing what DisplayClass and why it is created at compile time, etc. I'm only interested in its field value. One thing I can think of is reflection. With something like below, but that doesn't seem neat.
node.Value.GetType().GetFields()[0].GetValue(node.Value);
Bonus problem
While playing with the code for gettting id , I changed the VisitConstant method as shown below (which will not solve my problem) and get an exception saying that the "object" does not contain a definition for "id"

Bonus Question
How dynamics is resolved at runtime, and DisplayClass is created at compile time, why can't we access our fields with dynamic ? Although the code works below, I expected the code to work as well.
var st = new {Id = 1L}; object o = st; dynamic dy = o; Assert.AreEqual(1L, dy.Id);