【问题标题】:C# Refactoring gigantic switch statement for ordering with LINQC# 重构巨大的 switch 语句以使用 LINQ 进行排序
【发布时间】:2015-06-17 09:59:09
【问题描述】:
我的问题是重复代码:一个不太干的 switch 语句。
所以我有一个包含 12 列的表格,点击时可以按降序或升序排序。我目前的解决方案是使用 switch 语句来检查点击了哪一列。
可排序的属性:
如果用户点击头部,则在该页面中对表格进行排序:
SortByColumn 属性以字符串形式出现。 SortAscending 布尔值来自 @Html.CheckBoxFor。
你知道这是怎么回事吗?我有 12 列可以订购,所以这个开关会变得非常冗长且无法维护。所以我的问题是,是否可以通过反射或其他方式重构它?
【问题讨论】:
标签:
c#
asp.net-mvc
linq
dry
【解决方案1】:
OrderBy 函数的工作原理是让您返回它应该排序的属性,它将被称为列表中的每个项目。
我们可以使用反射代替硬编码:
public ActionResult Index(AgentReportViewModel vm)
{
var b = Agent.GetAgents();
vm.Agents = vm.SortAscending
? b.OrderBy(x => GetValueByColumn(x, vm.SortByColumn))
: b.OrderByDescending(x => GetValueByColumn(x, vm.SortByColumn));
return View(vm);
}
public object GetValueByColumn<T>(T x, string columnStr)
{
// Consider caching the property info, as this is a heavy call.
var propertyInfo = x.GetType().GetProperty(columnStr);
return propertyInfo.GetValue(x, null);
}
【解决方案2】:
您可以在这种情况下使用表达式树。
public static Func<Agent, object> GetOrderBySelector(string propertyName)
{
var parameter = Expression.Parameter(typeof(Agent), "a");
var property = Expression.Property(parameter, propertyName);
// a => a.PropertyName is a unary expression
var unaryExpression = Expression.Convert(property, typeof(object));
// Create the lambda for the unary expression with the given property
// information and compile to return the actual delegate.
return Expression.Lambda<Func<Agent, object>>(unaryExpression, parameter).Compile();
}
用法:
b.OrderBy(vm.SortByColumn)
或
b.OrderByDescending(vm.SortByColumn)
希望这会有所帮助。
【解决方案3】:
试试这个:
var SortByColumnStr = "Answer"; //Dynamic string
var propertyInfo = typeof(Agent).GetProperty(SortByColumnStr);
List<Agent> b.OrderBy(x => propertyInfo.GetValue(x, null));
参考:https://stackoverflow.com/a/7265394/1660178
【解决方案4】:
看看 System.Linq.Dynamic(NuGet 包可用)。
那么你可以这样做:
string sortingString = string.Format("{0} {1}",vm.OrderByColumn, vm.SortAscending ? "ASC" : "DESC");
vm.Agents = Agent.GetAgents().OrderBy(sortingString).ToList();