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

时间:2012-09-14 16:17:39

标签: c# asp.net linq generics expression

我的代码的行部分是重复的。

您将看到下面的lambda表达式重复4次

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

代码示例:

//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;
    }

我想采取第一行,并把它变成我可以进入OrderBy的东西。

类似的东西:

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

进入:

allEvents = _allEvents.OrderBy(sortLambda);

不幸的是,这似乎并没有奏效。

2 个答案:

答案 0 :(得分:1)

此控制台应用应该可以解决您的问题。 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;
    }
}

答案 1 :(得分:0)

我相信OrderBy方法需要Func<T1,T2>参数,所以你可能会这样做......

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

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