以下は、私の問題の簡単なデモ コードです。
[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
メソッドはVisitConstant
、2 つの異なるパスで呼び出されます。
1. TestParam
-> Search
->VisitConstant
この実行パスSearch
では、メソッドに渡される定数式 (1L) は実定数値です。ここでは、すべて問題ありません。 assert は期待どおりに成功します。VisitConstant
最初のパスnode.Value.GetType()
isInt64
およびその.Value
isを介して呼び出された場合1L
。
2. TestParam
-> GetStudent
-> Search
->VisitConstant
この実行パス定数式 (id: 1L) では、引数として取り、クロージャー内のメソッドにGetStudent
渡します。Search
問題
問題は 2 番目の実行パスにあります。がVisitConstant
2 番目のパスを介して呼び出されnode.Value.GetType()
、このクラスに(メソッドの引数と同じ)MyProject.Tests.ExpressionTests+<>c__DisplayClass0
という名前の public フィールドがあり、値が.id
GetStudent
1L
質問
id
2 番目のパスで値を取得するにはどうすればよいですか? DisplayClass
クロージャ、aとは何か、コンパイル時に作成される理由などについて知っています。フィールド値を取得することにのみ関心があります。私が考えることができることの1つは、反射によるものです。以下のようなものですが、きれいに見えません。
node.Value.GetType().GetFields()[0].GetValue(node.Value);
ボーナス問題
値を取得するためのコードで遊んでいるときに、以下のようにメソッドid
を変更しましVisitConstant
たが (これでは問題は解決しません)、「'object' には 'id' の定義が含まれていません」という例外が発生します。
ボーナス質問
ダイナミクスは実行時に解決さDisplayClass
れ、コンパイル時に作成されるため、なぜそのフィールドにアクセスできないのdynamic
ですか? 以下のコードは機能しますが、コードも機能することを期待していました。
var st = new {Id = 1L};
object o = st;
dynamic dy = o;
Assert.AreEqual(1L, dy.Id);