Предположим, мне нужно написать выражение посетителя, которое также использует некоторую инъекционную услугу, следовательно, он должен иметь открытый конструктор и не может быть просто завернут в статический фасад.Stateful Expression посетителей многократная проблема запуска
public class ProcessingVisitor : ExpressionVisitor {
IProcessor _processor;
public string Result { get; private set; }
public ProcessingVisitor(IProcessor processor) {
_processor = processor;
}
protected override Expression VisitBinary(BinaryExpression node)
{
// visit left and right
// ... and do something with _processor
Result += // ... append something to result
return node;
}
}
Теперь, когда я хочу использовать этот посетитель, я бы его экземпляр и использовать его как этот
var myExpression = ...;
var myVisitor = new ProcessingVisitor();
myVisitor.Visit(myExpression);
var result = myVisitor.Result;
Теперь представьте себе, я - например, случайно - запустить Visit
на другое выражение. Тогда Result
будет содержать оба конкатенированных результата. Как я могу сделать такого посетителя полностью «безумным доказательством»? Где я могу сбросить Result
? Я мог бы переопределить Visit
, но я не знаю внутри, если он вызван в первый раз, или он вызван в середине обработки, поэтому я не могу сбросить его там.
Не могли бы вы разместить код для 'Visit' - может быть, он находится в' ExpressionVisitor'? Кроме того, правильный конструктор 'ProcessingVisitor' корректен? – jnovo
Да, это потомок потомков Expression. Конструктор без параметров - ошибка, я исправлю его, спасибо. –
С точки зрения чистой архитектуры ваша проблема заключается в том, что вы добавили состояние в свой класс, но вы обнаружите, что состояние может привести к недействительному состоянию. Решение прост. Удалите состояние. Сделать вызов метода для синтаксического анализа дерева выражений, возвращающего строку, или путаницы с посещенным выражением и строкой – Aron