我正在尝试创建一个快速类,这样我就可以使网格的排序代码更容易编写和维护,并保持代码重复。要做到这一点,我想出了下面的类:如何动态存储用于Linq Orderby的表达式?
public class SortConfig<TSource, TRelatedObject> where TSource : class where TRelatedObject : class
{
public IList<SortOption> Options { get; protected set; }
public SortOption DefaultOption { get; set; }
public SortConfig()
{
Options = new List<SortOption>();
}
public void Add(string name, Expression<Func<TSource, object>> sortExpression, TRelatedObject relatedObject, bool isDefault = false)
{
var option = new SortOption
{
FriendlyName = name,
SortExpression = sortExpression,
RelatedObject = relatedObject
};
Options.Add(option);
if (isDefault)
DefaultOption = option;
}
public SortOption GetSortOption(string sortName)
{
if (sortName.EndsWith("asc", StringComparison.OrdinalIgnoreCase))
sortName = sortName.Substring(0, sortName.LastIndexOf("asc", StringComparison.OrdinalIgnoreCase));
else if (sortName.EndsWith("desc", StringComparison.OrdinalIgnoreCase))
sortName = sortName.Substring(0, sortName.LastIndexOf("desc", StringComparison.OrdinalIgnoreCase));
sortName = sortName.Trim();
var option = Options.Where(x => x.FriendlyName.Trim().Equals(sortName, StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
if (option == null)
{
if (DefaultOption == null)
throw new InvalidOperationException(
string.Format("No configuration found for sort type of '{0}', and no default sort configuration exists", sortName));
option = DefaultOption;
}
return option;
}
public class SortOption
{
public string FriendlyName { get; set; }
public Expression<Func<TSource, object>> SortExpression { get; set; }
public TRelatedObject RelatedObject { get; set; }
}
}
的想法是,你创建的不同排序选项,什么ORDERBY表达的快速配置用于那些,和可选的是关系到一个对象排序选项。这使我的代码看起来像:
protected void InitSortConfig()
{
_sortConfig = new SortConfig<xosPodOptimizedSearch, HtmlAnchor>();
_sortConfig.Add("name", (x => x.LastName), lnkSortName, true);
_sortConfig.Add("team", (x => x.SchoolName), lnkSortTeam);
_sortConfig.Add("rate", (x => x.XosRating), lnkSortRate);
_sortConfig.Add("pos", (x => x.ProjectedPositions), null);
_sortConfig.Add("height", (x => x.Height), lnkSortHeight);
_sortConfig.Add("weight", (x => x.Weight), lnkSortWeight);
_sortConfig.Add("city", (x => x.SchoolCity), lnkSortCity);
_sortConfig.Add("state", (x => x.SchoolState), lnkSortState);
}
,然后我可以只是做
// Get desired sorting configuration
InitSortConfig();
var sortOption = _sortConfig.GetSortOption(sort);
bool isDescendingSort = sort.EndsWith("desc", StringComparison.OrdinalIgnoreCase);
// Setup columns
InitSortLinks();
if (sortOption.RelatedObject != null)
{
// Make modifications to html anchor
}
// Form query
var query = PodDataContext.xosPodOptimizedSearches.AsQueryable();
if (isDescendingSort)
query = query.OrderByDescending(sortOption.SortExpression);
else
query = query.OrderBy(sortOption.SortExpression);
这个伟大的工程,当排序变量是一个字符串排序,但如果不是一个字符串,我得到以下例外:Cannot order by type 'System.Object'.
我假设这是因为我存储的表达式为Expression<Func<TSource, object>>
而不是关于该第二个泛型更具体。我不明白我如何在一个类中保留所有不同的排序选项(即使是非字符串属性)。
我猜测的问题之一是,Linq.OrderBy()
条款需要Expression<Func<TSource, TKey>>
,因为它的参数,但我不换我周围Linq.OrderBy()
如何能够推断TKey
应该是什么样的头,所以我不明白如何利用优势推断用适当的TKey
来存储这些表达式。
任何想法?
看看[这里](http://weblogs.asp.net/scottgu/archive/2008/01 /07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx) – Nestor
谢谢,但我宁愿排序代码指定,而不是字符串指定,特别是因为我的数据结构网格与我的数据库不是1:1数据模型,因此排序需要从网格指定的数据库转换为db排序 – KallDrexx
不管您是否使用排序选项,是不是在使用魔术字符串? –