[英]How to write generic IEnumerable<SelectListItem> extension method
I'm fairly new (ok, REALLy new) to generics but I love the idea of them. 我对泛型相当陌生(好,非常新),但是我喜欢它们的想法。 I am going to be having a few drop-down lists on a view and I'd like a generic way to take a list of objects and convert it to a list of SelectListItems
我将在视图上有一些下拉列表,并且我想要一种通用的方法来获取对象列表并将其转换为SelectListItems
列表
What I have now: 我现在所拥有的:
public static IEnumerable<SelectListItem> ToSelectListItems(
this IEnumerable<SpecificObject> items, long selectedId)
{
return
items.OrderBy(item => item.Name)
.Select(item =>
new SelectListItem
{
Selected = (item.Id == selectedId),
Text = item.Name,
Value = item.Id.ToString()
});
}
Trouble is, I'd need to repeat that code for each drop-down as the objects have different fields that represent the Text
property of the SelectListItem
麻烦的是,我需要为每个下拉列表重复该代码,因为对象具有表示SelectListItem
的Text
属性的不同字段。
Here is what I'd like to accomplish: 这是我想要完成的事情:
public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items, string key, string value, int SelectedId) {
// I really have no idea how to proceed from here :(
}
Well, you could do something like this: 好吧,您可以执行以下操作:
public static IEnumerable<SelectListItem> ToSelectListItems(
this IEnumerable<T> items,
Func<T,string> nameSelector,
Func<T,string> valueSelector,
Func<T,bool> selected)
{
return items.OrderBy(item => nameSelector(item))
.Select(item =>
new SelectListItem
{
Selected = selected(item),
Text = nameSelector(item),
Value = valueSelector(item)
});
}
You could pass in delegates to do the comparisons, and property retrieval. 您可以传入委托进行比较和属性检索。 Something like this: 像这样:
public static IEnumerable<SelectListItem> ToSelectListItem<T>(this IEnumerable<T> items,
int selectedId, Func<T,int> getId, Func<T, string> getName,
Func<T, string> getText, Func<T, string> getValue)
{
return
items.OrderBy(item => getName(item))
.Select(item =>
new SelectListItem
{
Selected = (getId(item) == selectedId),
Text = getText(item),
Value = getValue(item)
});
}
Then you would use it like so: 然后,您将像这样使用它:
var selected = specificObjects.ToSelectListItem(10, s => s.Id, s=> s.Name, s => s.Name, s => s.Id.ToString());
In order for this to work as written, your type T
will need to implement some interface which provides Name
and Id
properties: 为了使它按书面形式工作,您的T
类型将需要实现一些提供Name
和Id
属性的接口:
public interface ISelectable
{
string Name { get; }
int Id { get; }
}
With this in place, you can do: 完成此操作后,您可以执行以下操作:
public static IEnumerable<SelectListItem> ToSelectListItems<T>(this IEnumerable<T> items, long selectedId)
where T : ISelectable
{
return
items.OrderBy(item => item.Name)
.Select(item =>
new SelectListItem
{
Selected = (item.Id == selectedId),
Text = item.Name,
Value = item.Id.ToString()
});
}
This is required in order to use the Name
and Id
properties within your extension method... You could, instead, provide a different means of receiving these (ie: passing delegates), but that may or may not increase the maintenance cost in your scenario. 为了在扩展方法中使用Name
和Id
属性,这是必需的。相反,您可以提供一种不同的方式来接收这些属性(例如,传递委托),但这可能会或可能不会增加您的维护成本场景。
//You need to use reflection to get the value of //您需要使用反射来获取
public static IEnumerable<SelectListItem> GetListItems<T>
(this IEnumerable<T> items, int selectedVal)
{
return from item in items
select new SelectListItem
{
Text =item.GetPropValue("Name"),
Value = item.GetPropValue("Id"),
Selected =
item.GetPropValue("Id").Equals(selectedVal.ToString())
};
}
public static string GetPropValue<T> (this T item,string refName)
{
return
item.GetType().GetProperty(refName).GetValue(item).ToString();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.