尝试将一些逻辑封装在一个扩展方法中,该方法将在给定的IEnumerable上提供ToSelectList方法,但我遇到了障碍,我希望有人可以帮助我走上正确的轨道。
基本上,我有一个覆盖,没关系。我知道从给定基类使用的字段,代码如下所示:
public static IEnumerable<SelectListItem> ToSelectList(this IEnumerable<BaseModel> list)
{
return list.Select(t => new SelectListItem { Text = t.Description, Value = t.Id.ToString() });
}
不是问题。已知领域。当我想使用从BaseModel派生的类中的特定字段时,问题就出现了,但是想要从调用代码中指定那些字段以生成此方法的更通用版本。
基本上,我希望在调用代码中使用lambdas来指定我想从列表中的项目中检索的两个属性,如下所示:
myEnumerable.ToSelectList(textSelector => textSelector.Id.ToString(), valueSelector => valueSelector.DisplayName);
所以我的方法如下:
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<BaseModel> list, [DON'T KNOW WHAT GOES HERE] textExpression, [DON'T KNOW WHAT GOES HERE] valueExpression)
{
return list.Cast<T>().Select(t => new SelectListItem { Text = textExpression(t), Value = valueExpression(t).ToString() });
}
我正在尝试找出我需要做的事情,然后让我使用用于Select的表达式中的那些来将这些字段用作分配给SelectListItem
属性的值。我猜在LINQ IEnumerable<T>.ToDictionary
方法下面必须有类似的东西,其中有一个表达式的键,另一个表示该值。
这甚至可能吗?如果不是,我很乐意减少损失。然而,目前,我正在努力解决我需要传递给我的ToSelectList方法作为参数的问题 - 它是Expression<T>
,Func<T>
还是{{1} }?我不介意承认我在表达式评估中迷失了方法。
答案 0 :(得分:2)
您可以尝试以下
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<BaseModel> list, Expression<Func<T, string>> textExpression, Expression<Func<T, string>> valueExpression)
{
var textFunc = textExpression.Compile();
var valueFunc = valueExpression.Compile();
return list.Select(t => new SelectListItem
{
Text = textFunc(t),
Value = valueFunc(t)
});
}
或
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<BaseModel> list, Func<T, string> textFunc, Func<T, string> valueFunc)
{
return list.Select(t => new SelectListItem
{
Text = textFunc(t),
Value = valueFunc(t)
});
}
答案 1 :(得分:1)
你在这里不需要Expression<>
。普通Func<T, string>
会做得很好。
现在,我无法理解this IEnumerable<BaseModel> list
部分,特别是因为您稍后会list.Cast<T>()
。这样做会更干净:
IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T>,
Func<T, string> textProvider,
Func<T, string> idProvider)
where T : BaseModel