簡體   English   中英

Linq表達式 - >構建一個位置(...)。單個(...)Linq樹表達式

[英]Linq Expressions -> Build a Where(…).Single(…) Linq Tree Expression

我正在嘗試構建一個Expression<Func<TEntity, TKey>>如:

e.Collection.Where(c => c.Key.Equals("key")).Single()

所以,到目前為止,我已經能夠構建類似的東西了。 但是,我不太清楚如何構建Where().Single()鏈:

Type entityType = typeof(TElementType);
PropertyInfo collectionPropertyInfo = entityType.GetProperty("Metainfos"); // TODO: Pick the property up instead of using a literal string
if (collectionPropertyInfo == null)
    throw new MissingFieldException(string.Format("{0} collection doesn't appear in {1}", "MetaInfos", entityType));

Type collGenericType = collectionPropertyInfo.PropertyType.GetGenericArguments().FirstOrDefault();
if (!collGenericType.IsAssignableFrom(typeof(Domain.MetaInfoValue)))
    throw new TypeLoadException(string.Format("Collection generic type doesn't inherit from {1}", collGenericType));

ParameterExpression entityParameter = Expression.Parameter(entityType, "t");
ParameterExpression metaInfoParameterExpression = Expression.Parameter(collGenericType, "m");

MemberExpression collectionMemberExpression = Expression.Property(entityParameter, collectionPropertyInfo);
MethodInfo whereMethod = typeof(Enumerable).GetMethods().Where(m => m.Name.Equals("Where") && m.GetParameters().Length == 2).First().MakeGenericMethod(collGenericType);
MethodInfo singleMethod = typeof(Enumerable).GetMethods().Where(m => m.Name.Equals("Single") && m.GetParameters().Length == 1).First().MakeGenericMethod(collGenericType);

LambdaExpression innerCondition = Expression.Lambda(
    Expression.GetDelegateType(collGenericType, typeof(bool)),
    Expression.Equal(
        Expression.Property(metaInfoParameterExpression, "Key"),
        Expression.Constant(field)
    ),
    metaInfoParameterExpression
);

return Expression.Lambda<Func<TElementType, TKeyType>>(
    Expression.Call(
        singleMethod,
        Expression.Lambda<Func<TElementType, bool>>(
            Expression.Call(whereMethod, collectionMemberExpression, innerCondition), 
            entityParameter
        )
    )
);}

它拋出了一個ArgumentException

不允許使用System.Collections.Generic.IEnumerable1[Backend.Domain.MetaInfoValue]</code> for the returned value類型的表達式System.Collections.Generic.IEnumerable1[Backend.Domain.MetaInfoValue]</code> for the returned value System.Boolean`

怎么了?

似乎Expression.Call for Single就是問題所在。 您需要提供(1) source和(2) arguments 現在,您似乎試圖將它們作為相同的參數提供( Expression.Lambda<Func<TElementType, bool>>(Expression.Call(whereMethod, collectionMemberExpression, innerCondition), entityParameter); )。

想想Single表達式通常是什么樣的: myEnumerable.Single(o => o.Key == iKey); 看看你的SourcemyEnumerable )與你的選擇表達式有什么不同( o => o.Key == iKey )?

如果您創建兩個表達式作為Single調用的參數(一個source使用Enumerable輸入和輸出,一個選擇器( Expression.Lambda<Func<TElementType, bool>> ),它應該解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM