C# 重构巨大的 switch 语句以使用 LINQ 进行排序
C# Refactoring gigantic switch statement for ordering with LINQ
我的问题是重复代码:不太干的 switch 语句。
所以我有一个包含 12 列的 table,可以在点击时按降序或升序排序。我当前的解决方案是使用 switch 语句来检查单击了哪一列。
排序table属性:
这是一个页面,如果用户点击头像,table 就会被订购:
SortByColumn
属性 以字符串形式出现。 SortAscending
布尔值来自 @Html.CheckBoxFor
。
你知道这是怎么回事吗?我有 12 列可以订购,所以这个开关会变得非常冗长且难以维护。所以我的问题是,是否可以通过反射或其他方式重构它?
试试这个:
var SortByColumnStr = "Answer"; //Dynamic string
var propertyInfo = typeof(Agent).GetProperty(SortByColumnStr);
List<Agent> b.OrderBy(x => propertyInfo.GetValue(x, null));
参考:
OrderBy 函数的工作原理是让您 return 它应该排序的 属性,它将为列表中的每个项目调用。
我们可以使用反射代替硬编码:
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);
}
您可以在这种情况下使用表达式树。
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)
希望对您有所帮助。
看看 System.Linq.Dynamic(NuGet 包可用)。
那么你可以这样做:
string sortingString = string.Format("{0} {1}",vm.OrderByColumn, vm.SortAscending ? "ASC" : "DESC");
vm.Agents = Agent.GetAgents().OrderBy(sortingString).ToList();
我的问题是重复代码:不太干的 switch 语句。
所以我有一个包含 12 列的 table,可以在点击时按降序或升序排序。我当前的解决方案是使用 switch 语句来检查单击了哪一列。
排序table属性:
这是一个页面,如果用户点击头像,table 就会被订购:
SortByColumn
属性 以字符串形式出现。 SortAscending
布尔值来自 @Html.CheckBoxFor
。
你知道这是怎么回事吗?我有 12 列可以订购,所以这个开关会变得非常冗长且难以维护。所以我的问题是,是否可以通过反射或其他方式重构它?
试试这个:
var SortByColumnStr = "Answer"; //Dynamic string
var propertyInfo = typeof(Agent).GetProperty(SortByColumnStr);
List<Agent> b.OrderBy(x => propertyInfo.GetValue(x, null));
参考:
OrderBy 函数的工作原理是让您 return 它应该排序的 属性,它将为列表中的每个项目调用。
我们可以使用反射代替硬编码:
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);
}
您可以在这种情况下使用表达式树。
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)
希望对您有所帮助。
看看 System.Linq.Dynamic(NuGet 包可用)。
那么你可以这样做:
string sortingString = string.Format("{0} {1}",vm.OrderByColumn, vm.SortAscending ? "ASC" : "DESC");
vm.Agents = Agent.GetAgents().OrderBy(sortingString).ToList();