2012-09-17 45 views
1

我創建了一個LINQ表達式,將一個序列投影到匿名類型的新序列中,正如我在這裏找到的LINQ expression tree with anonymous typesLINQ表達式投射到匿名類型

這裏是我的表達I'would喜歡來執行:

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})} 

然後r沒有時間的錯誤是:

"Unexpected character '`'" 

有人可以幫我解碼這個嗎?

UPDATE:

這是我的實際電話:

var res = Expressions.DoExpression(typeof(Document), doc, "AllStatements.Select(new field=Amount, field1=Account)"); 

但是,有很多落後DoExpressions功能解析和LINQ表達式(500行代碼左右)

UPDATE 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的導航屬性,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」]。

現在,這不是我的代碼,我只是調整它以適應我一點點。這實際上是上面代碼片段的最後一行代碼。只有展開堆棧並進行編譯。

對不起,如果這可能沒有任何意義。如果您需要任何澄清,請詢問。

+0

你究竟在哪裏得到這些錯誤?在VS的「Watch」窗口中? – Spontifixus

+0

是的,我的結果是var類型。然後我在那之後放置一個斷點,然後檢查它(VS說'擴展結果視圖將枚舉IEnumerable')。然後我得到這些錯誤 –

+0

Watch內的字符串不是C#代碼,所以你不能以這種方式執行它。 – svick

回答

0

我認爲選擇需要在新的字段周圍的圓括號。

Select("new(<property1>,<property2>,...)"); 


var res = Expressions.DoExpression(typeof(Document), doc, "AllStatements.Select(new (field=Amount, field1=Account))"); 
+0

我沒有使用動態LINQ,在這種情況下我做了我自己的解析... –

0

嗯,我不能讓匿名的預測,但我裝箱小班和項目成:

public class LookupModel 
{ 
    public LookupModel(int id, string dsc) 
    { 
     ID = id; 
     DSC = dsc; 
    } 

    public int ID { get; set; } 
    public string DSC { get; set; } 
} 

因此,使用這樣的:

function LINQSelectNew(Expression expr, string[] args) 
{ 
Type type = expr.Type.GetGenericArguments()[0]; 
ParameterExpression parameter = Expression.Parameter(type, type.Name); 

List<Expression> lista = new List<Expression>();      
foreach (string s in args) lista.Add(Expressions.ResolveCompleteExpression(parameter, s.Prepare())); 

Expression New = Expression.New(typeof(LookupModel).GetConstructor(lista.Select(e => e.Type).ToArray()), lista.ToArray()); 

return Expression.Call(
    typeof(Queryable), 
    "Select", 
    new Type[] { type, New.Type }, 
    expr, 
    Expression.Lambda(New, new ParameterExpression[] { parameter })); 
} 

我可以這樣做:

var res = Expressions.DoExpression(
    typeof(Dokument), 
    doc, 
    "SviFinStavovi.Select(new LookupModel(amount, amount.ToString()))" 
); 

希望這有助於somebo dy ...