I've created a LINQ expression that projects a sequence into new sequence of anonymous types as I've found here LINQ expression tree with anonymous types.
Here is my expression I'would like to execute:
Document doc = ....;
doc.AllStatements.Select(s => new { field = s.Amount });
This is runtime representation of selector inside brackets:
{t => new field;Decimal;() {field = t.Amount}}
And this is runtime representation of whole expression.
{System.Linq.Enumerable+<UnionIterator>d__88`1[SISTEM.Models.Statement].Select(t => new field;Decimal;() {field = t.Amount})}
When I try to enumerate it during Debug I get just this:
") expected"
If I try with multiple field anonymous type like this:
doc.AllStatements.Select(s => new { field = s.Amount, field2 = s.Account });
I get this:
{System.Linq.Enumerable+<UnionIterator>d__88`1[SISTEM.Models.Statement].Select(t => new field;Decimal;field1;Nullable`1;() {field = t.Amount, field1 = t.Account})}
and then runtime error is:
"Unexpected character '`'"
Can somebody help me decode this?
UPDATE:
This is my actual call:
var res = Expressions.DoExpression(typeof(Document), doc, "AllStatements.Select(new field=Amount, field1=Account)");
But, there is a lot of parsing and LINQ expressions behind DoExpressions function (500 lines of code or so)
UPDATE 2:
First of all here is snippet of code:
Dokument doc = db.Dokumenti.First(); // Proper document, entity object;
var res = Expressions.DoExpression(
typeof(Dokument),
doc,
"SviFinStavovi.Select(new id=Iznos, dsc=Opis)"
);
SviFinStavovi is Navigational Property of Dokument, and Iznos and Opis are properties of underlying type of SviFinStavovi.
These 2 lines of code, though, don't throw exception. Exception will be thrown only when I try to enumerate res. You have those above.
If I had put SviFinStavovi.Select(Iznos), that would have worked OK.
This is 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 parses the whole thing.
Now, this is function that I got from this site, link above, which I added, and which causes trouble:
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);
}
At this point expr would represent (correctly) doc.SviFinStavovi, and field names would be ["id=Iznos"] ["dsc=Opis"].
Now, this is not my code, i just adjusted it to suit me little bit. This is effectively last executed line of code of the snippet above. Only to unwind stack and do the compile.
Sorry if this maybe doesn't make any sense. If you need any clarifications, please ask.