[英]IQueryable expression type mismatch
我想為LINQ表達式創建擴展方法,但是我遇到了麻煩。 我需要的只是創建一個將特定的Where子句添加到Queryable
。 就像是:
var hierarchy = "a string";
Session.Query<SomeClass>.Where(x => x.Layer.Hierarchy.StartsWith(hierarchy) ||
x.Layer.Hierarchy == hierarchy);
成為:
var hierarchy = "a string";
Session.Query<SomeClass>.LayerHierarchy(x => x.Layer, hierarchy);
並執行其中的邏輯。 因此,基本上,擴展方法LayerHierarchy()
在T
的Queryable
之上運行,但是主題的類型為Layer
:
public static IQueryable<T> LayerHierarchy<T>(this IQueryable<T> query,
Expression<Func<T, Layer>> layer,
string hierarchy)
{
var parameterExp = Expression.Parameter(typeof(Layer), "layer");
var propertyExp = Expression.Property(parameterExp, "Hierarchy");
// StartWith method
MethodInfo methodStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
var valueStartsWith = Expression.Constant(string.Concat(hierarchy, "|"), typeof(string));
var methodExpStartsWith = Expression.Call(propertyExp, methodStartsWith, valueStartsWith);
var startsWith = Expression.Lambda<Func<Layer, bool>>(methodExpStartsWith, parameterExp);
// Equals method
MethodInfo methodEquals = typeof(string).GetMethod("Equals", new[] { typeof(string) });
var valueEquals = Expression.Constant(hierarchy, typeof(string));
var methodExpEquals = Expression.Call(propertyExp, methodEquals, valueEquals);
var equals = Expression.Lambda<Func<Layer, bool>>(methodExpEquals, parameterExp);
return query
.Where(startsWith)
.Where(equals);
}
在return
線以上,一切正常。 它抱怨...
無法從
System.Linq.Expressions.Expression<System.Func<Layer, bool>>
為System.Linq.Expressions.Expression<System.Func<T, int, bool>>
嘗試將表達式傳遞給query.Where()
方法時。 我該如何解決?
好吧,問題在於您如何創建Lambda
。 它們應該從T
開始,而不是從Layer
:
var startsWith = Expression.Lambda<Func<T, bool>>(methodExpStartsWith, parameterExp);
var equals = Expression.Lambda<Func<T, bool>>(methodExpEquals, parameterExp);
但是,為了使其正常工作,您還缺少一個PropertyExpression
。
您的查詢現在看起來像:
(層)x => x.Hierarchy.StartsWith(...)
什么時候,您想要的是:
(T)x => x.Layer.Hierarchy.StartsWith(...)
因此,請改用此:
var parameterExp = Expression.Parameter(typeof(T), "item");
var layerExp = Expression.Property(parameterExp, "Layer");
var propertyExp = Expression.Property(layerExp, "Hierarchy");
但是,您的邏輯應該稍有變化,因為兩個.Where
會在它們之間生成一個AND
條件,並且似乎您希望其中一個為真( StartsWith
或Equals
),因此:
var parameterExp = Expression.Parameter(typeof(T), "item");
var layerExp = Expression.Property(parameterExp, "Layer");
var propertyExp = Expression.Property(layerExp, "Hierarchy");
// StartWith method
MethodInfo methodStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
var valueStartsWith = Expression.Constant(string.Concat(hierarchy, "|"), typeof(string));
var methodExpStartsWith = Expression.Call(propertyExp, methodStartsWith, valueStartsWith);
// Equals method
MethodInfo methodEquals = typeof(string).GetMethod("Equals", new[] { typeof(string) });
var valueEquals = Expression.Constant(hierarchy, typeof(string));
var methodExpEquals = Expression.Call(propertyExp, methodEquals, valueEquals);
var orElseExp = Expression.OrElse(methodExpStartsWith, methodExpEquals);
var orElse = Expression.Lambda<Func<T, bool>>(orElseExp, parameterExp);
return query.Where(orElse);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.