我想用这样的签名做一个方法:
Expression<Func<TSource, bool>> CreatePropertyFilter<TSource>(Expression<Func<TSource, string>> selector, string value, TextMatchMode matchMode);
基本上,它需要一个属性选择器(例如:p = p.Name
),一个字符串值和一个枚举值,可以是StartsWith
,EndsWith
,Contains
,{{ 1}};用于文本匹配选项。
如何以LINQ2Entities可以理解的方式实现该方法?我已经使用嵌套的调用表达式实现了这个方法,如下所示:
Exact
问题是Linq2Entities不支持调用表达式。
对此有何建议?
谢谢!
答案 0 :(得分:5)
基本上,给定一个选择器:
input => input.Member
您正在构建一个谓词表达式,如:
input => selector(input).Method(value)
相反,使用 body (MemberExpression
)'展开'选择器表达式,构造如下内容:
input => input.Member.Method(value)
这看起来像是:
private static Expression<Func<TSource, bool>> CreatePropertyFilter<TSource>
(Expression<Func<TSource, string>> selector,
string value,
TextMatchMode matchMode)
{
// Argument-checking here.
var body = selector.Body as MemberExpression;
if (body == null)
throw new ArgumentException("Not a MemberExpression.");
// string.StartsWith / EndsWith etc. depending on the matchMode.
var method = typeof(string)
.GetMethod(GetMethodName(matchMode), new[] { typeof(string) });
// input.Member.method(value)
var compEx = Expression.Call(body, method, Expression.Constant(value));
// We can reuse the parameter of the source.
return Expression.Lambda<Func<TSource, bool>>(compEx, selector.Parameters);
}
翻译方法是:
// I really don't like this enum.
// Why not explicitly include Equals as a member?
private static string GetMethodName(TextMatchMode mode)
{
switch (mode)
{
case TextMatchMode.StartsWith:
return "StartsWith";
case TextMatchMode.EndsWith:
return "EndsWith";
case TextMatchMode.Contains:
return "Contains";
default:
return "Equals";
}
}