强类型的动态Linq的排序 [英] Strongly typed dynamic Linq sorting

查看:180
本文介绍了强类型的动态Linq的排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立一些code动态排序一个LINQ的IQueryable<>

I'm trying to build some code for dynamically sorting a Linq IQueryable<>.

最明显的办法是在这里,这种种使用字符串字段名称
列表 <一href="http://dvanderboom.word$p$pss.com/2008/12/19/dynamically-composing-linq-orderby-clauses/">http://dvanderboom.word$p$pss.com/2008/12/19/dynamically-composing-linq-orderby-clauses/

The obvious way is here, which sorts a list using a string for the field name
http://dvanderboom.wordpress.com/2008/12/19/dynamically-composing-linq-orderby-clauses/

不过,我想要一个变化 - 编译字段名的时间检查,并使用重构/查找所有引用来支持后期维护的能力。这意味着我要定义字段为f => f.Name,而不是作为字符串。

However I want one change - compile time checking of field names, and the ability to use refactoring/Find All References to support later maintenance. That means I want to define the fields as f=>f.Name, instead of as strings.

有关我的具体使用方法我要封装了一些code,将决定哪些命名为排序依据EX pressions的清单应根据用户的输入使用,无需每次都写不同的code

For my specific use I want to encapsulate some code that would decide which of a list of named "OrderBy" expressions should be used based on user input, without writing different code every time.

下面是什么,我已经写了要点:

Here is the gist of what I've written:

var list = from m Movies select m; // Get our list

var sorter = list.GetSorter(...); // Pass in some global user settings object

sorter.AddSort("NAME", m=>m.Name);
sorter.AddSort("YEAR", m=>m.Year).ThenBy(m=>m.Year);

list = sorter.GetSortedList();

...
public class Sorter<TSource>
...
public static Sorter<TSource> GetSorter(this IQueryable<TSource> source, ...)

的GetSortedList函数确定使用哪个命名各种各样的,这导致在一个列表对象,其中每个FieldData包含AddSort传递的字段的的MethodInfo和类型的值:

The GetSortedList function determines which of the named sorts to use, which results in a List object, where each FieldData contains the MethodInfo and Type values of the fields passed in AddSort:

public SorterItem<TSource> AddSort(Func<T, TKey> field)
{
   MethodInfo ... = field.Method;
   Type ... = TypeOf(TKey);
   // Create item, add item to diction, add fields to item's List<>
   // The item has the ThenBy method, which just adds another field to the List<>
}

我不知道是否有一种方法来存储的方式,将允许它在稍后返回的整个领域对象(这将是不可能投,因为它是一个通用型)

I'm not sure if there is a way to store the entire field object in a way that would allow it be returned later (it would be impossible to cast, since it is a generic type)

有没有一种方法,我可以调整实例code,或拿出全新的code,因此,在使用强类型的字段名称排序后的的他们已存储在一些集装箱和恢复(丢失任何普通压铸类)

Is there a way I could adapt the sample code, or come up with entirely new code, in order to sort using strongly typed field names after they have been stored in some container and retrieved (losing any generic type casting)

推荐答案

这样做将有你的AddSort()函数采取防爆pression&LT最简单的方法,而不只是函数求电影>>;函数功能:LT 。这使您的排序方法来检查前pression提取出来,你要作为排序依据的属性的名称。然后,您可以在内部存储这个名字作为一个字符串,因此存储是很容易的,你可以使用您链接到排序算法,但你还可以获得类型安全和编译时检查有效的属性名。

The easiest way to do this would be to have your AddSort() function take an Expression<Func<Movie>> instead of just a Func. This allows your sort method to inspect the Expression to extract out the name of the property that you want to sort on. You can then store this name internally as a string, so storing is very easy and you can use the sorting algorithm you linked to, but you also get type safety and compile time checking for valid property names.

static void Main(string[] args)
{
	var query = from m in Movies select m;

	var sorter = new Sorter<Movie>();
	sorter.AddSort("NAME", m => m.Name);
}

class Sorter<T>
{
	public void AddSort(string name, Expression<Func<T, object>> func)
	{
		string fieldName = (func.Body as MemberExpression).Member.Name;
	}
}

在这种情况下,我使用对象作为FUNC的返回类型,因为它很容易自动转换,但你可以实现与不同类型或泛型,适当,如果你需要更多的功能。在这种情况下,由于前pression只是在那里进行检查,这其实并不重要。

In this case, i've used object as the return type of the func, because its easily automatically convertible, but you could implement that with different types, or generics, as appropriate, if you require more functionality. In this case, since the Expression is just there to be inspected, it doesn't really matter.

的其他可能的方法是,仍然需要函数求,并存储在辞典本身。然后,当谈到整理,你需要得到的值进行排序,你可以调用是这样的:

The other possible way is to still take a Func, and store that in the dictionary itself. Then, when it comes to sorting, and you need to get the value to sort on, you can call something like:

// assuming a dictionary of fields to sort for, called m_fields
m_fields[fieldName](currentItem)

这篇关于强类型的动态Linq的排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆