栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

IEnumerable上的动态LINQ OrderBy /可查询

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

IEnumerable上的动态LINQ OrderBy /可查询

刚发现这个老歌…

要在没有动态LINQ库的情况下执行此操作,您只需要以下代码。这涵盖了最常见的场景,包括嵌套属性。

要使其工作,

IEnumerable<T>
您可以添加一些可通过的包装器方法
AsQueryable
-但以下代码是
expression
所需的核心逻辑。

public static IOrderedQueryable<T> OrderBy<T>(    this IQueryable<T> source,     string property){    return ApplyOrder<T>(source, property, "OrderBy");}public static IOrderedQueryable<T> OrderByDescending<T>(    this IQueryable<T> source,     string property){    return ApplyOrder<T>(source, property, "OrderByDescending");}public static IOrderedQueryable<T> ThenBy<T>(    this IOrderedQueryable<T> source,     string property){    return ApplyOrder<T>(source, property, "ThenBy");}public static IOrderedQueryable<T> ThenByDescending<T>(    this IOrderedQueryable<T> source,     string property){    return ApplyOrder<T>(source, property, "ThenByDescending");}static IOrderedQueryable<T> ApplyOrder<T>(    IQueryable<T> source,     string property,     string methodName) {    string[] props = property.Split('.');    Type type = typeof(T);    Parameterexpression arg = expression.Parameter(type, "x");    expression expr = arg;    foreach(string prop in props) {        // use reflection (not ComponentModel) to mirror LINQ        PropertyInfo pi = type.GetProperty(prop);        expr = expression.Property(expr, pi);        type = pi.PropertyType;    }    Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);    Lambdaexpression lambda = expression.Lambda(delegateType, expr, arg);    object result = typeof(Queryable).GetMethods().Single( method => method.Name == methodName         && method.IsGenericMethodDefinition         && method.GetGenericArguments().Length == 2         && method.GetParameters().Length == 2) .MakeGenericMethod(typeof(T), type) .Invoke(null, new object[] {source, lambda});    return (IOrderedQueryable<T>)result;}

编辑:如果要与之混合使用,它会变得更加有趣

dynamic
-尽管请注意,这
dynamic
仅适用于LINQ-to-
Objects(ORM等的表达树不能真正表示
dynamic
查询-
Memberexpression
不支持它)。但是这是使用LINQ-to-
Objects的一种方法。注意,之所以选择
Hashtable
是由于有利的锁定语义:

using Microsoft.CSharp.RuntimeBinder;using System;using System.Collections;using System.Collections.Generic;using System.Dynamic;using System.Linq;using System.Runtime.CompilerServices;static class Program{    private static class AccessorCache    {        private static readonly Hashtable accessors = new Hashtable();        private static readonly Hashtable callSites = new Hashtable();        private static CallSite<Func<CallSite, object, object>> GetCallSiteLocked( string name)         { var callSite = (CallSite<Func<CallSite, object, object>>)callSites[name]; if(callSite == null) {     callSites[name] = callSite = CallSite<Func<CallSite, object, object>>         .Create(Binder.GetMember(          CSharpBinderFlags.None,name,typeof(AccessorCache),          new CSharpArgumentInfo[] {    CSharpArgumentInfo.Create(       CSharpArgumentInfoFlags.None,        null)})); } return callSite;        }        internal static Func<dynamic,object> GetAccessor(string name)        { Func<dynamic, object> accessor = (Func<dynamic, object>)accessors[name]; if (accessor == null) {     lock (accessors )     {         accessor = (Func<dynamic, object>)accessors[name];         if (accessor == null)         {  if(name.IndexOf('.') >= 0) {      string[] props = name.Split('.');      CallSite<Func<CallSite, object, object>>[] arr= Array.ConvertAll(props, GetCallSiteLocked);      accessor = target =>      {          object val = (object)target;          for (int i = 0; i < arr.Length; i++)          {   var cs = arr[i];   val = cs.Target(cs, val);          }          return val;      };  } else {      var callSite = GetCallSiteLocked(name);      accessor = target =>      {          return callSite.Target(callSite, (object)target);      };  }  accessors[name] = accessor;         }     } } return accessor;        }    }    public static IOrderedEnumerable<dynamic> OrderBy(        this IEnumerable<dynamic> source,         string property)    {        return Enumerable.OrderBy<dynamic, object>( source,  AccessorCache.GetAccessor(property),  Comparer<object>.Default);    }    public static IOrderedEnumerable<dynamic> OrderByDescending(        this IEnumerable<dynamic> source,         string property)    {        return Enumerable.OrderByDescending<dynamic, object>( source,  AccessorCache.GetAccessor(property),  Comparer<object>.Default);    }    public static IOrderedEnumerable<dynamic> ThenBy(        this IOrderedEnumerable<dynamic> source,         string property)    {        return Enumerable.ThenBy<dynamic, object>( source,  AccessorCache.GetAccessor(property),  Comparer<object>.Default);    }    public static IOrderedEnumerable<dynamic> ThenByDescending(        this IOrderedEnumerable<dynamic> source,         string property)    {        return Enumerable.ThenByDescending<dynamic, object>( source,  AccessorCache.GetAccessor(property),  Comparer<object>.Default);    }    static void Main()    {        dynamic a = new ExpandoObject(),      b = new ExpandoObject(),      c = new ExpandoObject();        a.X = "abc";        b.X = "ghi";        c.X = "def";        dynamic[] data = new[] {  new { Y = a }, new { Y = b },  new { Y = c }         };        var ordered = data.OrderByDescending("Y.X").ToArray();        foreach (var obj in ordered)        { Console.WriteLine(obj.Y.X);        }    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/465586.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号