简体   繁体   English

System.Linq.Expressions.Expression for .OrderBy函数

[英]System.Linq.Expressions.Expression for .OrderBy function

I have a line section of my code that is repetitive. 我的代码的行部分是重复的。

You will see the lambda expression below repeat 4 times 您将看到下面的lambda表达式重复4次

x => x.GetValue<string>("City")).ThenByDescending(x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString())

The code example : 代码示例:

//SORT DATA
    switch (SortDetails)
    {
        case ("Date"):
        default:
            if (SortOrder == "ASC")
            {
                _allEvents = _allEvents.OrderBy(x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString()));
            }
            else
            {
                _allEvents = _allEvents.OrderByDescending(x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString()));
            }
            break;
        case ("Location"):
            if (SortOrder == "ASC")
            {
                _allEvents = _allEvents.OrderBy(x => x.GetValue<string>("Country")).ThenBy(x => x.GetValue<string>("ProvinceState")).ThenBy(x => x.GetValue<string>("City")).ThenBy(x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString()));
            }
            else
            {
                _allEvents = _allEvents.OrderByDescending(x => x.GetValue<string>("Country")).ThenByDescending(x => x.GetValue<string>("ProvinceState")).ThenByDescending(x => x.GetValue<string>("City")).ThenByDescending(x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString()));
            }
            break;
    }

I would like to take the first line and make it into something I can just plop into the OrderBy's. 我想采取第一行,并使其成为我可以进入OrderBy的东西。

Something like : 就像是 :

System.Linq.Expressions.Expression<Func<DynamicContent, DateTime>> sortLambda = x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString());

into : 进入:

allEvents = _allEvents.OrderBy(sortLambda);

Unfortunately that didn't seem to work well. 不幸的是,这似乎并没有奏效。

This console app should fix you up. 这个控制台应用程序应该修复你。 The sortLamda can be of any type, which hopefully answers your question about Dynamic Content. sortLamda可以是任何类型,希望能回答有关动态内容的问题。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

internal class BoringEvent
{
    public string EventStartStr { get; set; }
    public string EventTimeZone { get; set; }
    public string ProvinceState { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

internal enum SortedBy
{
    Ascending = 0,
    Descending
}

class ExpressionsTest
{
    internal static List<BoringEvent> _allEvents = new List<BoringEvent>();
    internal static class HelperFunctions
    {
        public static DateTime strToTZDateTime(string startDate, 
            string timeZone)
        {
            //I'm too lazy to figure out dates by time zone.
            //Your function already has the logic, so why bother.
            //Let's assume the time zone is equal in this test case
            return DateTime.Parse(startDate);
        }
    }

    internal static void Main()
    {

        _allEvents.Add(new BoringEvent {
            EventStartStr = "12/31/1999", 
            //let's party like it's 1999 - (yawn) I'm stuck at this event :< 
            EventTimeZone = "en-us", 
            City = "Philadelphia", 
            ProvinceState = "Pennsylvania",
            Country = "United States of America"});
        _allEvents.Add(new BoringEvent
        {
            EventStartStr = "01/01/1970",
            EventTimeZone = "en-us",
            City = "New York",
            ProvinceState = "New York",
            Country = "United States of America"
        });
        IEnumerable<BoringEvent> sortedEvents = null;
        //sort by date
        Console.WriteLine("Sorting Events by Ascending date...");
        Expression<Func<BoringEvent, DateTime>> sortLamba = evt => HelperFunctions.strToTZDateTime(evt.EventStartStr, evt.EventTimeZone);
        sortedEvents = _allEvents.SortEvents(SortedBy.Ascending, sortLamba);
        Print(sortedEvents);
        //sort by country, then state, then city, then date
        Console.WriteLine("Sorting Events Desc by Country, then ProvinceState, then City, then Date");
        Expression<Func<BoringEvent, object>>[] sortLamba2 = new Expression<Func<BoringEvent, object>>[] 
        {
            evt => evt.Country,
            evt => evt.ProvinceState,
            evt => evt.City,
            evt => HelperFunctions.strToTZDateTime(evt.EventStartStr, evt.EventTimeZone)
        };
        sortedEvents = _allEvents.SortEvents(SortedBy.Descending, sortLamba2);   
        Print(sortedEvents);

        Console.Read();
    }

    private static void Print(IEnumerable<BoringEvent> events)
    {
        for(int i = 0; i < events.Count(); i++)
        {
            BoringEvent evt = events.ElementAt(i);
            Console.WriteLine("Event: {0}", i.ToString());
            Console.WriteLine("\tEventStartStr: {0}", evt.EventStartStr);
            Console.WriteLine("\tEventTimeZone: {0}", evt.EventTimeZone);
            Console.WriteLine("\tCity: {0}", evt.City);
            Console.WriteLine("\tProvinceState: {0}", evt.ProvinceState);
            Console.WriteLine("\tCountry: {0}", evt.Country);
        }
    }
}

internal static class EventExtensions
{

    public static IEnumerable<TResult> SortEvents<TResult, T>(
        this IEnumerable<TResult> events, 
        SortedBy sortByType,
        params Expression<Func<TResult, T>>[] expressions)
    {
        IEnumerable<TResult> retVal = null;
        switch(sortByType)
        {
            case SortedBy.Ascending:
                retVal = EventExtensions.SortEventsAsc(events, expressions);
                break;
            case SortedBy.Descending:
                retVal = EventExtensions.SortEventsDesc(events, expressions);
                break;
            default:
                throw new InvalidOperationException(
                    string.Format("The SortedBy enumeration does not contain a case for the value of '{0}'.", 
                    Enum.GetName(typeof(SortedBy), sortByType)));
        }
        return retVal;
    }

    public static IEnumerable<TResult> SortEventsAsc<TResult, T>(
        this IEnumerable<TResult> events, 
        params Expression<Func<TResult, T>>[] expressions)
    {
        IOrderedEnumerable<TResult> sorted = null;
        for(int i = 0; i < expressions.Count(); i++)
        {
            Expression<Func<TResult, T>> exp = 
                (Expression<Func<TResult, T>>)expressions[i];
            Func<TResult, T> deleg = exp.Compile();
            if(i == 0)
            {
                sorted = events.OrderBy(evt => deleg.Invoke(evt));
            }
            else
            {
                sorted = sorted.ThenBy(evt => deleg.Invoke(evt));
            }
        }
        return sorted;
    }

    public static IEnumerable<TResult> SortEventsDesc<TResult, T>(
        this IEnumerable<TResult> events,
        params Expression<Func<TResult, T>>[] expressions)
    {
        IOrderedEnumerable<TResult> sorted = null;
        for (int i = 0; i < expressions.Count(); i++)
        {
            Expression<Func<TResult, T>> exp = 
                (Expression<Func<TResult, T>>)expressions[i];
            Func<TResult, T> deleg = exp.Compile();
            if (i == 0)
            {
                sorted = events.OrderByDescending(evt => deleg.Invoke(evt));
            }
            else
            {
                sorted = sorted.ThenByDescending(evt => deleg.Invoke(evt));
            }
        }
        return sorted;
    }
}

I believe that the OrderBy method takes a Func<T1,T2> parameter, so you could possibly do this... 我相信OrderBy方法采用Func<T1,T2>参数,所以你可能会这样做......

var func = x => HelperFunctions.strToTZDateTime(x.GetValue<string>("EventStartStr"), x.GetValue<string[]>("EventTimeZone")[0].ToString());

then pass func into _allEvents = _allEvents.OrderBy(func); 然后将func传递给_allEvents = _allEvents.OrderBy(func);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何评估System.Linq.Expressions.Expression - How to evaluate a System.Linq.Expressions.Expression 获取System.Linq.Expressions.Expression对象的类型 - Get type of System.Linq.Expressions.Expression object 如何使用System.Linq.Expressions.Expression根据子项进行过滤? - How to use System.Linq.Expressions.Expression to filter based on children? 将In和NotIn添加到System.Linq.Expressions.Expression中,是否可能? - Adding In and NotIn to System.Linq.Expressions.Expression, is it possible? IQStreamable:无法从“字符串”转换为“ System.Linq.Expressions.Expression” - IQStreamable: cannot convert from 'string' to 'System.Linq.Expressions.Expression C# lambda 返回 System.Linq.Expressions.Expression 的问题 - Issue with C# lambda return System.Linq.Expressions.Expression 什么是System.Linq.Expressions.Expression中的TKey <Func<TSource,TKey> &gt;? - What is TKey in System.Linq.Expressions.Expression<Func<TSource,TKey>>? 如何为Like创建System.Linq.Expressions.Expression? - How to create a System.Linq.Expressions.Expression for Like? 如何从System.Linq.Expressions.Expression中删除括号? - How to remove Parantheses from System.Linq.Expressions.Expression? 无法从“ System.Linq.Expressions.LambdaExpression”转换为“ System.Linq.Expressions.Expression” - Cannot convert from 'System.Linq.Expressions.LambdaExpression' to 'System.Linq.Expressions.Expression
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM