การสั่งซื้อ LINQ แบบไดนามิกโดยใช้ IE จำนวน <T> / IQueryable <T>


668

ผมพบว่าตัวอย่างเช่นในที่VS2008 ตัวอย่างแบบไดนามิก LINQ ที่ช่วยให้คุณใช้ SQL เหมือนสตริง (เช่นOrderBy("Name, Age DESC"))สำหรับการสั่งซื้อ. แต่วิธีการที่รวมการทำงานเฉพาะบนIQueryable<T>. มีวิธีที่จะได้รับการทำงานนี้ที่ใดIEnumerable<T>?


1
คำตอบที่ดีที่สุด ณ วันนี้ในความคิดของฉัน: System.Linq.Dynamic.Core library
Shahin Dohan

คำตอบ:


904

เพิ่งเข้ามาใน Oldie นี้ ...

ในการทำเช่นนี้โดยไม่ต้องมีห้องสมุด LINQ แบบไดนามิกคุณเพียงแค่ต้องการรหัสดังต่อไปนี้ สิ่งนี้ครอบคลุมสถานการณ์ทั่วไปส่วนใหญ่รวมถึงคุณสมบัติแบบซ้อน

เพื่อให้มันทำงานกับIEnumerable<T>คุณสามารถเพิ่มวิธีการ wrapper ที่ผ่าน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 เท่านั้น (expression-trees สำหรับ ORMs และอื่น ๆ ไม่สามารถแสดงถึงการ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);
        }
    }
}

109
ชิ้นแช่งที่ดีที่สุดของรหัสที่ฉันได้เห็น :) เพียงแค่แก้ปัญหาล้านในโครงการของฉัน :)
sajidnizami

4
@Dave - คุณต้องเริ่มต้นด้วยIQueryable<T>ดังนั้นหากคุณมีสิ่งที่ชอบList<T>(ซึ่งก็คือIEnumerable<T>) คุณอาจจำเป็นต้องใช้AsQueryable()ตัวอย่างเช่นvar sorted = someList.AsQueryable().OrderBy("Foo.Bar");
Marc Gravell

7
คุณเคยเห็นสิ่งนี้หรือไม่ ... มันอาจช่วยให้บางคน ... stackoverflow.com/questions/557819/…เป็นโซลูชันที่พิมพ์ได้ดีกว่า
anthonyv

28
@MGOwen คุณดูเหมือนจะเข้าใจผิดธรรมชาติของรหัส 40 บรรทัดเหมือนกันไม่ว่าจะเป็น 40 บรรทัดที่คุณใส่ไว้ในโครงการของคุณหรือถ้าบรรทัดเหล่านั้นมา (รวบรวมไว้ล่วงหน้าหรือเป็นแหล่งที่มา) ในไลบรารีภายนอก คงจะน่าอัศจรรย์มากถ้าฉันเชื่อมโยงในเดือนตุลาคม '08 กับไลบรารีบน nuget ที่มีอยู่ตั้งแต่ ธ.ค. 11 (ไม่น้อยเพราะ nuget ไม่มีอยู่แล้ว) แต่พื้นฐาน "สิ่งที่มันทำ" คือ เหมือน. นอกจากนี้คุณยังใช้วลี "ทางออกที่แท้จริง" ราวกับว่ามีเส้นทางเดียวที่ตกลงกันอย่างดีสำหรับทุกคำถามในการเข้ารหัส: ไม่มี
Marc Gravell

5
@MGOwen btw, lib ภายนอกคือ 2296 บรรทัดของรหัส (ไม่รวม AssemblyInfo.cs); ชนิดไหนที่ทำให้ 40 บรรทัดตรงนี้ดูสมเหตุสมผล
Marc Gravell

231

ง่ายเกินไปโดยไม่มีภาวะแทรกซ้อนใด ๆ :

  1. เพิ่มusing System.Linq.Dynamic;ที่ด้านบน
  2. ใช้ vehicles = vehicles.AsQueryable().OrderBy("Make ASC, Year DESC").ToList();

11
และคุณได้รับSystem.Linq.Dynamicจากที่ไหน
Dementic

1
ทำงานเมื่อใช้ linq กับ MongoDB เช่นกัน
soupy1976

32
คำตอบที่ยอมรับอาจเป็นคำตอบที่ถูกต้องในปี 2008 แต่ปัจจุบันนี้เป็นคำตอบที่ง่ายที่สุดและถูกต้องที่สุดในขณะนี้
EL MOJO

1
นี่คือการจัดการที่ดีและเรียบง่ายจริงๆความซับซ้อนมากภายในรักมัน
Mrinal Kamboj

5
สำหรับผู้ที่อยู่ใน "อนาคต" หากคุณใช้ดอทเน็ตคอร์ให้ใช้สิ่งนี้: nuget.org/packages/System.Linq.Dynamic.Core
Rafael Merlin

78

ฉันพบคำตอบ ฉันสามารถใช้.AsQueryable<>()วิธีการขยายเพื่อแปลงรายการของฉันเป็น IQueryable แล้วเรียกใช้คำสั่งแบบไดนามิกโดยเทียบกับมัน


52
โปรดให้ตัวอย่างแก่พวกเราที่เหลือ
MGOwen

54

เพิ่งสะดุดกับคำถามนี้

จากการใช้การใช้ ApplyOrder ของ Marc จากข้างบนฉันตบวิธีส่วนขยายที่จัดการกับสตริงคล้าย SQL เช่น:

list.OrderBy("MyProperty DESC, MyOtherProperty ASC");

รายละเอียดสามารถพบได้ที่นี่: http://aonnull.blogspot.com/2010/08/dynamic-sql-like-linq-orderby-extension.html


1
สิ่งที่ยอดเยี่ยมเพียงเพิ่มการแก้ไขดังต่อไปนี้เพื่อทำให้ชื่อคุณสมบัติ case insensitive: PropertyInfo pi = type.GetProperty (prop, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
Mrinal Kamboj

43

ฉันคิดว่ามันจะใช้การสะท้อนเพื่อให้ได้ทรัพย์สินใด ๆ ที่คุณต้องการเรียงลำดับ:

IEnumerable<T> myEnumerables
var query=from enumerable in myenumerables
          where some criteria
          orderby GetPropertyValue(enumerable,"SomeProperty")
          select enumerable

private static object GetPropertyValue(object obj, string property)
{
    System.Reflection.PropertyInfo propertyInfo=obj.GetType().GetProperty(property);
    return propertyInfo.GetValue(obj, null);
}

โปรดทราบว่าการใช้การสะท้อนค่อนข้างช้ากว่าการเข้าถึงคุณสมบัติโดยตรงดังนั้นประสิทธิภาพจะต้องถูกตรวจสอบ


มันใช้งานได้หรือไม่ orderby ไม่ต้องการค่า แต่เป็นตัวเลือก lamba / ผู้รับมอบสิทธิ์ (Func <TSource, TKey> keySelector) ..
Davy Landman

2
ฉันลองตัวอย่างนี้ก่อนโพสต์และใช่มันใช้งานได้
Kjetil Watnedal

3
+1 นี่คือสิ่งที่ฉันกำลังมองหา! วิธีนี้จะใช้งานได้ดีสำหรับปัญหาการเรียงหน้าง่าย
Andrew Siemer

สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันพลาดอะไรไปรึเปล่า? "ทรัพย์สินบางอย่าง" ควรเป็นอย่างไร ฉันพยายามให้ชื่อคุณสมบัติเช่นเดียวกับ property.GetType () ฉันมี IQueryable <> และไม่ใช่ IEnumerable <>
ผู้ใช้ SO

2
@Alex Shkor: คุณจะเรียงลำดับองค์ประกอบโดยไม่ต้องดูองค์ประกอบทั้งหมดได้อย่างไร อย่างไรก็ตามมีคำตอบที่ดีกว่าในคำตอบอื่น ๆ
Kjetil Watnedal

19

เพียงแค่สร้างสิ่งที่คนอื่นพูด ฉันพบว่าการทำงานต่อไปนี้ค่อนข้างดี

public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> input, string queryString)
{
    if (string.IsNullOrEmpty(queryString))
        return input;

    int i = 0;
    foreach (string propname in queryString.Split(','))
    {
        var subContent = propname.Split('|');
        if (Convert.ToInt32(subContent[1].Trim()) == 0)
        {
            if (i == 0)
                input = input.OrderBy(x => GetPropertyValue(x, subContent[0].Trim()));
            else
                input = ((IOrderedEnumerable<T>)input).ThenBy(x => GetPropertyValue(x, subContent[0].Trim()));
        }
        else
        {
            if (i == 0)
                input = input.OrderByDescending(x => GetPropertyValue(x, subContent[0].Trim()));
            else
                input = ((IOrderedEnumerable<T>)input).ThenByDescending(x => GetPropertyValue(x, subContent[0].Trim()));
        }
        i++;
    }

    return input;
}

12

ฉันสะดุดคำถามนี้เพื่อหาคำสั่ง Linq หลายคำสั่งและบางทีนี่อาจเป็นสิ่งที่ผู้เขียนกำลังมองหา

นี่คือวิธีการ:

var query = pets.OrderBy(pet => pet.Name).ThenByDescending(pet => pet.Age);    

5
+1 ยกเลิกการลงคะแนนเนื่องจากไม่มีคำอธิบาย ฉันยังคิดว่าผู้แต่งอาจสนใจสั่งซื้อหลายครั้ง แม้ว่าไดนามิกเป็นคำสำคัญไม่มีเหตุผลที่จะลงคะแนน
Jason Kleban

11

ฉันพยายามทำสิ่งนี้ แต่มีปัญหากับวิธีแก้ปัญหาของ Kjetil Watnedalเพราะฉันไม่ได้ใช้ไวยากรณ์ inline linq - ฉันชอบไวยากรณ์ของวิธีการ IComparerปัญหาของผมก็คือในการพยายามที่จะทำแบบไดนามิกการเรียงลำดับโดยใช้กำหนดเอง

โซลูชันของฉันสิ้นสุดลงเช่นนี้:

ได้รับแบบสอบถาม IQueryable ดังนี้:

List<DATA__Security__Team> teams = TeamManager.GetTeams();
var query = teams.Where(team => team.ID < 10).AsQueryable();

และรับอาร์กิวเมนต์ฟิลด์การจัดเรียงแบบรันไทม์:

string SortField; // Set at run-time to "Name"

OrderBy แบบไดนามิกดูเหมือนว่า:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField));

และนั่นคือการใช้เมธอดตัวช่วยเล็กน้อยที่เรียกว่า GetReflectedPropertyValue ():

public static string GetReflectedPropertyValue(this object subject, string field)
{
    object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null);
    return reflectedValue != null ? reflectedValue.ToString() : "";
}

หนึ่งสิ่งสุดท้าย - ฉันบอกว่าฉันต้องการOrderByที่จะใช้กำหนดเองIComparer- เพราะฉันอยากจะทำเรียงลำดับตามธรรมชาติ

เมื่อต้องการทำเช่นนั้นฉันเพิ่งเปลี่ยนเป็นOrderBy:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField), new NaturalSortComparer<string>());

ดูโพสต์นี้NaturalSortComparer()สำหรับรหัสสำหรับ


5

ใช้แบบไดนามิก linq

เพียงเพิ่ม using System.Linq.Dynamic;

และใช้สิ่งนี้เพื่อสั่งซื้อคอลัมน์ทั้งหมดของคุณ:

string sortTypeStr = "ASC"; // or DESC
string SortColumnName = "Age"; // Your column name
query = query.OrderBy($"{SortColumnName} {sortTypeStr}");

4

คุณสามารถเพิ่ม:

public static IEnumerable<T> OrderBy( this IEnumerable<T> input, string queryString) {
    //parse the string into property names
    //Use reflection to get and sort by properties
    //something like

    foreach( string propname in queryString.Split(','))
        input.OrderBy( x => GetPropertyValue( x, propname ) );

    // I used Kjetil Watnedal's reflection example
}

GetPropertyValueฟังก์ชั่นจากคำตอบของเคอร์วิน Watnedal

ปัญหาจะเป็นเพราะอะไร การเรียงลำดับใด ๆ จะทำให้เกิดข้อยกเว้นในเวลาทำงานแทนที่จะรวบรวมเวลา (เช่นคำตอบของ D2VIANT)

หากคุณกำลังจัดการกับ Linq ถึง Sql และ orderby เป็นต้นไม้แสดงผลมันจะถูกแปลงเป็น SQL เพื่อดำเนินการต่อไป


GetPropertyValue mehotod จะถูกดำเนินการสำหรับองค์ประกอบทั้งหมดมันเป็นทางออกที่ไม่ดี
Alex Shkor

2
OrderByไม่รักษาลำดับก่อนหน้า !!
อาเมียร์อิสมาอิล

4

นี่คือสิ่งอื่นที่ฉันคิดว่าน่าสนใจ หากแหล่งที่มาของคุณคือ DataTable คุณสามารถใช้การจัดเรียงแบบไดนามิกโดยไม่ใช้ Dynamic Linq

DataTable orders = dataSet.Tables["SalesOrderHeader"];
EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         orderby order.Field<DateTime>("OrderDate")
                                         select order;
DataView view = query.AsDataView();
bindingSource1.DataSource = view;

อ้างอิง: http://msdn.microsoft.com/en-us/library/bb669083.aspx (ใช้ DataSetExtensions)

นี่เป็นอีกวิธีหนึ่งที่ทำได้โดยแปลงเป็น DataView:

DataTable contacts = dataSet.Tables["Contact"];    
DataView view = contacts.AsDataView();    
view.Sort = "LastName desc, FirstName asc";    
bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

4

ขอบคุณ Maarten ( สอบถามชุดสะสมโดยใช้คุณสมบัติ PropertyInfo ใน LINQ ) ฉันได้รับโซลูชันนี้:

myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();

ในกรณีของฉันฉันกำลังทำงานกับ "ColumnHeaderMouseClick" (WindowsForm) ดังนั้นเพิ่งพบคอลัมน์เฉพาะที่กดและตัวแทนของ PropertyInfo:

foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
    if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
    {}
}

หรือ

PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();

(ต้องแน่ใจว่ามีชื่อคอลัมน์ของคุณตรงกับคุณสมบัติของวัตถุ)

ไชโย


4

หลังจากการค้นหาสิ่งนี้ได้ผลมากสำหรับฉัน:

public static IEnumerable<TEntity> OrderBy<TEntity>(this IEnumerable<TEntity> source, 
                                                    string orderByProperty, bool desc)
{
    string command = desc ? "OrderByDescending" : "OrderBy";
    var type = typeof(TEntity);
    var property = type.GetProperty(orderByProperty);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
    var resultExpression = Expression.Call(typeof(Queryable), command, 
                                           new[] { type, property.PropertyType },
                                           source.AsQueryable().Expression, 
                                           Expression.Quote(orderByExpression));
    return source.AsQueryable().Provider.CreateQuery<TEntity>(resultExpression);
}


3

โซลูชันสำรองใช้คลาส / อินเตอร์เฟสต่อไปนี้ มันไม่ได้เป็นแบบไดนามิกอย่างแท้จริง แต่ใช้งานได้

public interface IID
{
    int ID
    {
        get; set;
    }
}

public static class Utils
{
    public static int GetID<T>(ObjectQuery<T> items) where T:EntityObject, IID
    {
        if (items.Count() == 0) return 1;
        return items.OrderByDescending(u => u.ID).FirstOrDefault().ID + 1;
    }
}

2

คำตอบนี้เป็นการตอบกลับความคิดเห็นที่ต้องการตัวอย่างสำหรับวิธีการแก้ปัญหาที่ได้รับจาก @John Sheehan - Runscope

โปรดให้ตัวอย่างแก่พวกเราที่เหลือ

ใน DAL (Data Access Layer)

รุ่น IEnumerable:

  public  IEnumerable<Order> GetOrders()
    {
      // i use Dapper to return IEnumerable<T> using Query<T>
      //.. do stuff
      return  orders  // IEnumerable<Order>
  }

รุ่น IQueryable

  public IQueryable<Order> GetOrdersAsQuerable()
    {
        IEnumerable<Order> qry= GetOrders();
        //use the built-in extension method  AsQueryable in  System.Linq namespace
        return qry.AsQueryable();            
    }

ตอนนี้คุณสามารถใช้เวอร์ชัน IQueryable เพื่อเชื่อมโยงตัวอย่างเช่น GridView ใน Asp.net และประโยชน์สำหรับการจัดเรียง (คุณไม่สามารถเรียงลำดับโดยใช้ IEnumerable version)

ฉันใช้ Dapper เป็น ORM และสร้าง IQueryable version และใช้การเรียงลำดับใน GridView ใน asp.net ง่ายมาก


2

ติดตั้งเครื่องมือแบบไดนามิก -> NuGet Package Manager -> Console Manager Package

install-package System.Linq.Dynamic

เพิ่มNamespace using System.Linq.Dynamic;

ตอนนี้คุณสามารถใช้ OrderBy("Name, Age DESC")


ฉันจะใช้กับคุณสมบัติการเรียงลำดับภายในได้อย่างไร - เช่น OrderBy ("Branch.BranchName", "Descending")
devC

มันใช้งานได้สำหรับฉัน อาจเป็นเพราะคำถามมีอายุ 10 ปีและวิธีการที่ง่ายกว่านี้เกิดขึ้นในภายหลังเท่านั้น
kosherjellyfish

1

คุณสามารถใช้สิ่งนี้:

        public List<Book> Books(string orderField, bool desc, int skip, int take)
{
    var propertyInfo = typeof(Book).GetProperty(orderField);

    return _context.Books
        .Where(...)
        .OrderBy(p => !desc ? propertyInfo.GetValue(p, null) : 0)
        .ThenByDescending(p => desc ? propertyInfo.GetValue(p, null) : 0)
        .Skip(skip)
        .Take(take)
        .ToList();
}

สองสามปีต่อมาและฉันสะดุดกับสิ่งนี้; สิ่งนี้ได้ผลกับฉันเหมือนความฝัน ฉันมีการเรียงลำดับแบบไดนามิกในคุณสมบัติ 1 ถึง 3 และทำงานได้เหมือนฝัน ใช้งานง่ายและไม่ยุ่งยาก
Bazïnga

0

แปลงรายการเป็น IEnumerable หรือ Iquerable เพิ่มโดยใช้ System.LINQ.Dynamic namespace จากนั้นคุณสามารถพูดถึงชื่อคุณสมบัติในสตริงที่คั่นด้วยเครื่องหมายจุลภาคเป็นวิธี OrderBy ซึ่งมาจากค่าเริ่มต้นจาก System.LINQ.Dynamic


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.