用于生成SelectListItem列表的IQueryable扩展方法
本文关键字:IQueryable 扩展 方法 列表 SelectListItem 用于 | 更新日期: 2024-09-25 23:30:54
我正在处理返回IQueryable对象的存储库。
因此,我创建了一个扩展方法来返回SelectListItem
列表以用于我的视图:
public static List<SelectListItem> ToSelectList<T>(this IQueryable<T> query, Func<T, string> value, Func<T, string> text)
{
return query.Select(x => new SelectListItem() { Text = text(x), Value = value(x) }).ToList();
}
我这样称呼:
var query = Repository<MyClass>.GetAll(); //Return MyClass IQueryable
var test = query.ToSelectList(x => x.Property1, x => x.Property2);
它工作得很好(返回正确的列表),但SQL生成的select all属性来自MyClass。我希望在数据库中只查询Property1和Property2。
我在那里错过了什么?
从数据库检索结果x
后,会调用传入的委托,因此会返回所有字段。您可以传入表达式,然后将它们组合为一个表达式:
public static List<SelectListItem> ToSelectList<T>(this IQueryable<T> query, Expression<Func<T, object>> value, Expression<Func<T, string>> text)
{
var valueSrc = getProperty(value);
var textSrc = getProperty(text);
var x = Expression.Parameter(typeof(T),"x");
var type = typeof(SelectListItem);
var textProp = type.GetProperty("Text");
var valueProp = type.GetProperty("Value");
// x.valueSrc
Expression valueExpr = Expression.Property(x,valueSrc);
// (x.valueSrc).ToString()
if (valueExpr.Type == typeof(int))
{
var toStringMethod = typeof(int).GetMethod("ToString",Type.EmptyTypes);
valueExpr = Expression.Call(valueExpr,toStringMethod);
}
//x => new SelectListItem { Text = x.textSrc, Value = valueExpr }
var lambda = Expression.Lambda<Func<T,SelectListItem>>(
Expression.MemberInit(
Expression.New(type),
Expression.Bind(textProp,Expression.Property(x,textSrc)),
Expression.Bind(valueProp,valueExpr)),
x);
return query.Select(lambda).ToList();
}
static PropertyInfo getProperty(LambdaExpression exp)
{
var body = exp.Body;
//x => (object) x.Property
var ue = body as UnaryExpression;
if (ue != null)
body = ue.Operand;
return (PropertyInfo) ((MemberExpression) body).Member;
}
您可能需要在一个新的匿名对象上只选择您需要的属性,然后执行创建SelectListItem 的选择
类似的东西
return query.Select(p => new { value = value(p), text = text(p) ).Select(p => new SelectListItem(...) ;