Я создал выражение LINQ, которое проецирует последовательность в новую последовательность анонимных типов, как я нашел здесь Дерево выражений LINQ с анонимными типами.
Вот мое выражение, которое я хотел бы выполнить:
Document doc = ....;
doc.AllStatements.Select(s => new { field = s.Amount });
Это представление селектора внутри скобок во время выполнения:
{t => new field;Decimal;() {field = t.Amount}}
И это представление всего выражения во время выполнения.
{System.Linq.Enumerable+<UnionIterator>d__88`1[SISTEM.Models.Statement].Select(t => new field;Decimal;() {field = t.Amount})}
Когда я пытаюсь перечислить его во время отладки, я получаю только это:
") expected"
Если я попытаюсь использовать анонимный тип с несколькими полями, например:
doc.AllStatements.Select(s => new { field = s.Amount, field2 = s.Account });
Я получаю это:
{System.Linq.Enumerable+<UnionIterator>d__88`1[SISTEM.Models.Statement].Select(t => new field;Decimal;field1;Nullable`1;() {field = t.Amount, field1 = t.Account})}
а затем ошибка времени выполнения:
"Unexpected character '`'"
Может ли кто-нибудь помочь мне расшифровать это?
ОБНОВИТЬ:
Это мой настоящий звонок:
var res = Expressions.DoExpression(typeof(Document), doc, "AllStatements.Select(new field=Amount, field1=Account)");
Но за функцией DoExpressions стоит множество синтаксических анализов и выражений LINQ (500 строк кода или около того).
ОБНОВЛЕНИЕ 2:
Прежде всего, вот фрагмент кода:
Dokument doc = db.Dokumenti.First(); // Proper document, entity object;
var res = Expressions.DoExpression(
typeof(Dokument),
doc,
"SviFinStavovi.Select(new id=Iznos, dsc=Opis)"
);
СвиФинСтавови — Навигационное Свойство Документа, а Износ и Опись — свойства базового типа СвиФинСтавови.
Однако эти 2 строки кода не вызывают исключения. Исключение будет выдано только тогда, когда я попытаюсь перечислить res. У вас есть те, что выше.
Если бы я поставил СвиФинСтавови.Выбрать(Износ), то все бы работало нормально.
Это DoExpression:
public static object DoExpression(Type t, object obj, string expression){
ParameterExpression pe = Expression.Parameter(obj.GetType(), "objekat");
Expression SelectExpr = Expressions.ResolveCompleteExpression(pe, expression.Prepare());
return Expression.Lambda(SelectExpr, pe).Compile().DynamicInvoke(obj);}
ResolveCompleteExpression анализирует все это.
Теперь это функция, которую я получил с этого сайта, ссылка выше, которую я добавил, и которая вызывает проблемы:
public static Expression SelectDynamic(Expression expr, IEnumerable<string> fieldNames)
{
Type source = expr.Type.GetGenericArguments()[0];
Dictionary<string, PropertyInfo> sourceProperties = new Dictionary<string, PropertyInfo>();
foreach (string arg in fieldNames) sourceProperties.Add(arg.Split('=')[0].Trim(), source.GetProperty(arg.Split('=')[1].Trim()));
Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicTypeWrapper(sourceProperties);
ParameterExpression sourceItem = Expression.Parameter(source, "t");
IEnumerable<MemberBinding> bindings = dynamicType.GetFields().Select(p => Expression.Bind(p, Expression.Property(sourceItem, sourceProperties[p.Name]))).OfType<MemberBinding>();
Expression selector = Expression.Lambda(Expression.MemberInit(
Expression.New(dynamicType.GetConstructor(Type.EmptyTypes)), bindings), sourceItem);
return Expression.Call(typeof(Queryable), "Select", new Type[] { source, dynamicType }, expr, selector);
}
В этот момент expr будет представлять (правильно) doc.SviFinStavovi, а имена полей будут ["id=Iznos"] ["dsc=Opis"].
Теперь это не мой код, я просто немного подкорректировал его, чтобы он подходил мне. Фактически это последняя выполняемая строка кода фрагмента выше. Только раскрутить стек и выполнить компиляцию.
Извините, если это, возможно, не имеет никакого смысла. Если нужны какие-либо разъяснения, спрашивайте.