我创建了一个 LINQ 表达式,它将一个序列投影到新的匿名类型序列中,正如我在这里找到的LINQ expression tree with anonymous types。
这是我想要执行的表达式:
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)"
);
SviFinStavovi 是 Dokument 的 Navigational Property,Iznos 和 Opis 是 SviFinStavovi 底层类型的属性。
但是,这两行代码不会引发异常。只有当我尝试枚举 res 时才会抛出异常。你有上面的那些。
如果我放了 SviFinStavovi.Select(Iznos),那就可以了。
这是 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"]。
现在,这不是我的代码,我只是稍微调整一下以适合我。这实际上是上面代码片段的最后执行的代码行。仅用于展开堆栈并进行编译。
对不起,如果这可能没有任何意义。如果您需要任何澄清,请询问。