[英]Parameterized Linq Expression Help
I want to do a method with a signature like this: 我想做一个签名如下的方法:
Expression<Func<TSource, bool>> CreatePropertyFilter<TSource>(Expression<Func<TSource, string>> selector, string value, TextMatchMode matchMode);
Basically, it takes a property selector (ex: p = p.Name
), a string value and a enum value that can be StartsWith
, EndsWith
, Contains
, Exact
; 基本上,它需要一个属性选择器(例如: p = p.Name
),一个字符串值和一个枚举值,可以是StartsWith
, EndsWith
, Contains
, Exact
; for text matching options. 用于文本匹配选项。
How can I implement the method in a way that LINQ2Entities can understand? 如何以LINQ2Entities可以理解的方式实现该方法? I already implemented the method using nested invocation expressions like this: 我已经使用如下嵌套调用表达式实现了该方法:
Expression<Func<string, bool>> comparerExpression;
switch (matchMode)
{
case TextMatchMode.StartsWith:
comparerExpression = p => p.StartsWith(value);
break;
case TextMatchMode.EndsWith:
comparerExpression = p => p.EndsWith(value);
break;
case TextMatchMode.Contains:
comparerExpression = p => p.Contains(value);
break;
default:
comparerExpression = p => p.Equals(value);
break;
}
var equalityComparerParameter = Expression.Parameter(typeof(IncomingMail), null);
var equalityComparerExpression = Expression.Invoke(comparerExpression, Expression.Invoke(selector, equalityComparerParameter));
var equalityComparerPredicate = Expression.Lambda<Func<IncomingMail, bool>>(equalityComparerExpression, equalityComparerParameter);
The problem is that Linq2Entities doesn't support Invocation expressions. 问题在于Linq2Entities不支持调用表达式。
Any advice on this? 有什么建议吗?
Thanks! 谢谢!
Essentially, given a selector: 本质上,给定一个选择器:
input => input.Member
You are currently constructing a predicate expression like: 您当前正在构造一个谓词表达式,例如:
input => selector(input).Method(value)
Instead, 'expand' out the selector expression by using its body (a MemberExpression
), to construct something like: 取而代之的是,使用选择器表达式的主体 ( MemberExpression
)来“扩展”选择器表达式,以构造如下内容:
input => input.Member.Method(value)
This would look like: 看起来像:
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);
}
Where the translating method is: 翻译方法是:
// 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";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.