像这样的东西:
public static IQueryable<T> FilterObjectSet<T>(IQueryable<T> inputQuery,
Rule rule) where T : class
{
var par = Expression.Parameter(typeof(T));
var prop = Expression.PropertyOrField(par, rule.field);
var propType = prop.Member.MemberType == System.Reflection.MemberTypes.Field ?
((FieldInfo)prop.Member).FieldType :
((PropertyInfo)prop.Member).PropertyType);
// I convert the data that is a string to the "correct" type here
object data2 = Convert.ChangeType(rule.data,
propType,
CultureInfo.InvariantCulture);
var eq = Expression.Equal(prop, Expression.Constant(data2));
var lambda = Expression.Lambda<Func<T, bool>>(eq, par);
return inputQuery.Where(lambda);
}
如果你需要一些解释,你可以问。请注意,这不适用于具有特殊隐式转换的MyString
类型(例如具有 from 隐式转换的类型string
)。这是因为Convert.ChangeType
只使用IConvertible
接口。
空值处理data
也许是应该处理的其他事情。
请注意,我不确定Expression.PropertyOrField
是否由各种IQueryable<T>
引擎(LINQ-to-SQL 和 EF)处理。我只用AsQueryable()
引擎测试过。如果他们不“接受”它,则必须将其拆分为 a Expression.Property
或Expression.Field
取决于是什么rule.field
。
一个几乎等效的版本,不使用Expression.PropertyOrField
:
public static IQueryable<T> FilterObjectSet<T>(IQueryable<T> inputQuery,
Rule rule) where T : class
{
Type type = typeof(T);
var par = Expression.Parameter(type);
Type fieldPropertyType;
Expression fieldPropertyExpression;
FieldInfo fieldInfo = type.GetField(rule.field);
if (fieldInfo == null)
{
PropertyInfo propertyInfo = type.GetProperty(rule.field);
if (propertyInfo == null)
{
throw new Exception();
}
fieldPropertyType = propertyInfo.PropertyType;
fieldPropertyExpression = Expression.Property(par, propertyInfo);
}
else
{
fieldPropertyType = fieldInfo.FieldType;
fieldPropertyExpression = Expression.Field(par, fieldInfo);
}
object data2 = Convert.ChangeType(rule.data, fieldPropertyType);
var eq = Expression.Equal(fieldPropertyExpression,
Expression.Constant(data2));
var lambda = Expression.Lambda<Func<T, bool>>(eq, par);
return inputQuery.Where(lambda);
}