我有这个表达式树:
internal static IEnumerable<ElemType> WhereIn<ElemType>(this IEnumerable<ElemType> query, string filterFieldName, string[] values)
{
ParameterExpression lambdaParam = Expression.Parameter(typeof(ElemType), "p");
MethodCallExpression paramToString = Expression.Call(Expression.PropertyOrField(lambdaParam, filterFieldName), typeof(object).GetMethod("ToString"));
MethodInfo mi = typeof(Enumerable).GetMethods().Where(x => string.Equals(x.Name, "Contains", StringComparison.OrdinalIgnoreCase)).Single(x => x.GetParameters().Length == 2).MakeGenericMethod(typeof(string));
Expression<Func<string[]>> array = () => values;
MethodCallExpression contains = Expression.Call(mi, array.Body, paramToString);
LambdaExpression lambdaExp = Expression.Lambda<Func<ElemType, bool>>(contains, lambdaParam);
Func<ElemType, bool> lambda = (Func<ElemType, bool>)lambdaExp.Compile();
return query.Where(lambda);
}
现在,当使用像query.WhereIn("propName", new string[] {"aaa", "bbb"})
之类的东西调用它时,我并不总是希望代码创建一个新的表达式树,因为这样做非常耗时。但.Compile()
函数没有提供允许我使用编译的lambda的参数。 (或者,我只是不明白如何正确使用它。)
如何重写上面的表达式树以允许我缓存编译结果并为生成的编译lambda提供字符串数组?
答案 0 :(得分:0)
您应该创建和管理自己的缓存
缓存的关键应该是属性名称。
关键概念是创建一个关闭函数,引用数组(咖喱函数)
这是您在运行时基本上需要创建的内容
获取数组并返回其他函数的函数,该函数匹配相同的参数并返回linq where function的函数。
#include
在运行时编译表达式树并使用属性名作为缓存键的整个解决方案。
let inputString = "PRICE 9.00\nTAX 3.54\nTOTAL 12.54\n\nCASH 12.54\n\nTHANK YOU FOR SHOPPING!\nReceipt Code: 1HI 12D0 00A 0024" //want to grab this 14 character code"
let searchString = "Receipt Code: "
if let firstFound = inputString.rangeOfString(searchString)?.first {
let code = inputString.substringWithRange(firstFound.advancedBy(searchString.characters.count)..<firstFound.advancedBy(searchString.characters.count+17))
.stringByReplacingOccurrencesOfString(" ", withString: "") // "1HI12D000A0024"
}
答案 1 :(得分:0)
fast-member怎么样? 然后你的方法是:
private static Func<string, string[], Func<ElemType, bool>> CreatePredicate()
{
var accessor = TypeAccessor.Create(ElemType);
return (fieldName, arr) => (elem => arr.Contains((string)accessor[elem, fieldName]);
}
你可以这样做:
var filterFactory = CreatePredicate()
query.Where(filterFactory("MyProperty", new[] { "aaa", "bbb" }));