Я пишу парсер выражений, чтобы сделать мой API более удобным для рефакторинга и менее подверженным ошибкам.
по сути, я хочу, чтобы пользователь написал такой код:
repository.Get(entity => entity.Id == 10);
вместо:
repository.Get<Entity>("Id", 10);
Извлечение имени члена из левой части двоичного выражения было прямым.
Проблемы начались, когда я попытался извлечь значение из правой части выражения.
Вышеприведенный фрагмент демонстрирует простейший возможный случай, который включает в себя постоянное значение
но это может быть намного сложнее, включая замыкания, а что нет.
Поработав некоторое время, я перестал пытаться охватить все возможные случаи самостоятельно.
и решил использовать каркас, чтобы выполнить всю тяжелую работу за меня, скомпилировав и выполнив правую часть выражения.
соответствующая часть кода выглядит так:
public static KeyValuePair<string, object> Parse<T>(Expression<Func<T, bool>> expression)
{
var binaryExpression = (BinaryExpression)expression.Body;
string memberName = ParseMemberName(binaryExpression.Left);
object value = ParseValue(binaryExpression.Right);
return new KeyValuePair<string, object>(memberName, value);
}
private static object ParseValue(Expression expression)
{
Expression conversionExpression = Expression.Convert(expression, typeof(object));
var lambdaExpression = Expression.Lambda<Func<object>>(conversionExpression);
Func<object> accessor = lambdaExpression.Compile();
return accessor();
}
Теперь я получаю исключение InvalidOperationException (параметр Lambda не входит в область действия) в строке компиляции. Когда я гуглил решение, я столкнулся с похожими вопросами, которые включали создание выражения вручную и не предоставляли все части, или пытались опираться на параметры, имеющие одно и то же имя, а не одну и ту же ссылку. Я не думаю, что это так, потому что я снова использую данное выражение.
EDIT
Это один из нерабочих сценариев:
ExpressionParser.Parse (entity => entity.InternalClass.Id == entity.Id);
Буду признателен, если кто-нибудь подскажет мне об этом.
Спасибо.