我需要能够将属性的表达式应用于该属性的包装器,下面是一个示例;一个数字列表和一个列表包装数字,表达式是[数字是偶数]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace ExpressionTest
{
class Program
{
static void Main(string[] args)
{
/* Expression */
Expression<Func<int, bool>> expression = item => item % 2 == 0;
/* List */
IList<int> items = new List<int>();
for (int i = 0; i < 10; i++)
{
items.Add(i);
}
IEnumerable<int> evenNumbers = items.Where(expression.Compile());
foreach (int number in evenNumbers)
{
Console.WriteLine(number.ToString());
}
/* Wrappers List */
// How to apply expression to the porpery 'Number'?
IList<Wrapper> wrappers = new List<Wrapper>();
for (int i = 0; i < 10; i++)
{
wrappers.Add(new Wrapper { Number = i });
}
IEnumerable<int> evenWrappedNumbers = ????;
foreach (Wrapper wrappedNumber in evenWrappedNumbers)
{
Console.WriteLine(wrappedNumber.ToString());
}
}
}
public class Wrapper
{
public int Number;
}
}
答案 0 :(得分:7)
这应该可以解决问题:
Func<int, bool> predicate = expression.Compile();
IEnumerable<Wrapper> evenWrappedNumbers = wrappers.Where(w => predicate(w.Number));
或者如果你想要IEnumerable<int>
Func<int, bool> predicate = expression.Compile();
IEnumerable<int> evenWrappedNumbers = wrappers.Where(w => predicate(w.Number)).Select(w => w.Number);
编辑:自从了解NHibernate正在使用中,这是另一种可能的解决方案。请记住,我不使用NHibernate并且对表达树的经验有限。但无论如何,这应该允许NHibernate将表达式树解析为SQL。
首先在静态类中定义一个扩展方法,如下所示:
public static IQueryable<T> Where<T, TProperty>(this IQueryable<T> source,
Expression<Func<T, TProperty>> propertySelector,
Expression<Func<TProperty, bool>> predicate)
{
MemberExpression member = propertySelector.Body as MemberExpression;
if (member == null)
throw new ArgumentException("Must be a property selector", "propertySelector");
string propertyName = member.Member.Name;
// The input type
ParameterExpression propertyParameter = Expression.Parameter(typeof(T));
// The property on that type
MemberExpression itemProperty = Expression.Property(propertyParameter, propertyName);
// Invoke the specified predicate with the property from the input type
InvocationExpression invokeExpression = Expression.Invoke(predicate, itemProperty);
// The lambda expression for use with Linq
Expression<Func<T, bool>> finalExpression = Expression.Lambda<Func<T, bool>>(invokeExpression, propertyParameter);
return source.Where(finalExpression);
}
然后可以像这样使用这种扩展方法:
IEnumerable<Wrapper> evenWrappedNumbers = wrappers.Where(w => w.Number, expression);
正如我所说,我没有使用NHibernate的经验,但希望它能解析这个表达式树并将其转换为SQL。
答案 1 :(得分:0)
以下是一些不使用表达式的方法。我猜你想要Lukazoid的解决方案。
Expression<Func<Wrapper, bool>> expressionNew = item => item.Number % 2 == 0;
和此:
IEnumerable<int> evenWrappedNumbers = wrappers.Where(item => item.Number % 2 == 0);