Деревья выражений / операторов

Обновленный вопрос дальше вниз '

я экспериментировал с деревьями выражений в .NET 4 для генерации кода во время выполнения, и ямы пытались реализоватьforeach утверждение путем построения дерева выражений.

В конце выражение должно быть в состоянии генерировать делегата, который делает это:

Action action = source => 
{
  var enumerator = source.GetEnumerator();
  while(enumerator.MoveNext())
  {
    var i = enumerator.Current;
    // the body of the foreach that I don't currently have yet
  }
}

Мы придумали следующий вспомогательный метод, который генерирует BlockExpression из IEnumerable:

public static BlockExpression ForEachExpr(this IEnumerable source, string collectionName, string itemName)
{
        var item = Expression.Variable(typeof(T), itemName);

        var enumerator = Expression.Variable(typeof(IEnumerator), "enumerator");

        var param = Expression.Parameter(typeof(IEnumerable), collectionName);

        var doMoveNext = Expression.Call(enumerator, typeof(IEnumerator).GetMethod("MoveNext"));

        var assignToEnum = Expression.Assign(enumerator, Expression.Call(param, typeof(IEnumerable).GetMethod("GetEnumerator")));

        var assignCurrent = Expression.Assign(item, Expression.Property(enumerator, "Current"));

        var @break = Expression.Label();

        var @foreach = Expression.Block(
            assignToEnum,
            Expression.Loop(
                Expression.IfThenElse(
                Expression.NotEqual(doMoveNext, Expression.Constant(false)),
                    assignCurrent
                , Expression.Break(@break))
            ,@break)
        );
        return @foreach;

}

Следующий код:

var ints = new List { 1, 2, 3, 4 };
var expr = ints.ForEachExpr("ints", "i");
var lambda = Expression.Lambda(expr, Expression.Parameter(typeof(IEnumerable), "ints"));

Создает это дерево выражений:

.Lambda #Lambda1(System.Collections.Generic.IEnumerable`1[System.Int32] $ints)
{
    .Block() {
        $enumerator = .Call $ints.GetEnumerator();
        .Loop  {
            .If (.Call $enumerator.MoveNext() != False) {
                $i = $enumerator.Current
            } .Else {
                .Break #Label1 { }
            }
        }
        .LabelTarget #Label1:
    }
}

Это вроде бы нормально, но звонюCompile в этом выражении выдается исключение:

"variable 'enumerator' of type 'System.Collections.Generic.IEnumerator`1[System.Int32]' referenced from scope '', but it is not defined"

Didn»Я определяю это здесь:?

    var enumerator = Expression.Variable(typeof(IEnumerator), "enumerator");

Конечно, пример здесь надуман и непока не имеет практического применения, но яЯ пытаюсь получить представление о деревьях выражений, которые имеют тела, чтобы динамически объединять их во время выполнения в будущем.

РЕДАКТИРОВАТЬ: Моя первоначальная проблема была решена Александрой, спасибо! Конечно я'мы столкнулись с следующей проблемой сейчас. Я'мы объявилиBlockExpression в котором есть переменная. Внутри этого выражения я хочу другое выражение, которое ссылается на эту переменную. Но я неФактическая ссылка на эту переменную, только ее имя, потому что выражение предоставляется извне.

var param = Expression.Variable(typeof(IEnumerable), "something");

var block = Expression.Block(
                new [] { param },
                body
            );

body переменная передается извне и не имеет прямой ссылки наparam, но знает имя переменной в выражении ("something"). Это выглядит так:

var body = Expression.Call(typeof(Console).GetMethod("WriteLine",new[] { typeof(bool) }), 
               Expression.Equal(Expression.Parameter(typeof(IEnumerable), "something"), Expression.Constant(null)));

Это "код" что это порождает:

.Lambda #Lambda1(System.Collections.Generic.IEnumerable`1[System.Int32] $something)
{
    .Block(System.Collections.Generic.IEnumerable`1[System.Int32] $something) {
        .Call System.Console.WriteLine($something== null)
    }
}

Тем не менее, это нет компилировать. С той же ошибкой, что и раньше.

TLDR: Как мне ссылаться на переменную по идентификатору в дереве выражений?

Ответы на вопрос(3)

Ваш ответ на вопрос