11

以下は、私の問題の簡単なデモ コードです。

[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およびその.Valueisを介して呼び出された場合1L

2. TestParam -> GetStudent-> Search->VisitConstant

この実行パス定数式 (id: 1L) では、引数として取り、クロージャー内のメソッドにGetStudent渡します。Search

問題

問題は 2 番目の実行パスにあります。がVisitConstant2 番目のパスを介して呼び出されnode.Value.GetType()、このクラスに(メソッドの引数と同じ)MyProject.Tests.ExpressionTests+<>c__DisplayClass0という名前の public フィールドがあり、値が.idGetStudent1L

質問

id2 番目のパスで値を取得するにはどうすればよいですか? 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);
4

2 に答える 2

4

これは、それを行う方法を説明する記事であり、それを行うコードが含まれています。基本的に、できることは、その部分式だけを表す式を作成し、それをデリゲートにコンパイルしてから、そのデリゲートを実行することです。(この記事では、評価可能な部分式を特定する方法についても説明していますが、あなたはそれには興味がないと思います。)

この記事のコードを使用して、コードを次のように変更すると機能します。

private void Search<T>(Expression<Func<T, bool>> filter)
{
    new MyExpressionVisitor().Visit(Evaluator.PartialEval(filter));
}

ダイナミクスは実行時に解決さDisplayClassれ、コンパイル時に作成されるため、なぜそのフィールドにアクセスできないのdynamicですか?

これは 内にネストされDisplayClassたクラスであるため、内部のコードはそのメンバーにアクセスできません。privateExpressionTestsMyExpressionVisitor

内にMyExpressionVisitorネストされたクラスを作成すると、は で作業を開始します。ExpressionTestsdynamicDisplayClass

匿名型は、ネストされたprivate型として出力されないため、このようには動作しません。

于 2014-09-11T23:06:25.143 に答える