Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7891635
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 3, 20262026-06-03T06:40:08+00:00 2026-06-03T06:40:08+00:00

I am trying to create a quick class so that I can make writing

  • 0

I am trying to create a quick class so that I can make writing sorting code for a grid much easier to work with and maintain, and to keep code repetition down. To do this I came up with the following class:

public class SortConfig<TSource, TRelatedObject> where TSource : class where TRelatedObject : class
{
    public IList<SortOption> Options { get; protected set; }
    public SortOption DefaultOption { get; set; }

    public SortConfig()
    {
        Options = new List<SortOption>();
    }

    public void Add(string name, Expression<Func<TSource, object>> sortExpression, TRelatedObject relatedObject, bool isDefault = false)
    {
        var option = new SortOption
        {
            FriendlyName = name,
            SortExpression = sortExpression,
            RelatedObject = relatedObject
        };

        Options.Add(option);

        if (isDefault)
            DefaultOption = option;
    }

    public SortOption GetSortOption(string sortName)
    {
        if (sortName.EndsWith("asc", StringComparison.OrdinalIgnoreCase))
            sortName = sortName.Substring(0, sortName.LastIndexOf("asc", StringComparison.OrdinalIgnoreCase));
        else if (sortName.EndsWith("desc", StringComparison.OrdinalIgnoreCase))
            sortName = sortName.Substring(0, sortName.LastIndexOf("desc", StringComparison.OrdinalIgnoreCase));

        sortName = sortName.Trim();

        var option = Options.Where(x => x.FriendlyName.Trim().Equals(sortName, StringComparison.OrdinalIgnoreCase))
                            .FirstOrDefault();
        if (option == null)
        {
            if (DefaultOption == null)
                throw new InvalidOperationException(
                    string.Format("No configuration found for sort type of '{0}', and no default sort configuration exists", sortName));

            option = DefaultOption;
        }

        return option;
    }

    public class SortOption
    {
        public string FriendlyName { get; set; }
        public Expression<Func<TSource, object>> SortExpression { get; set; }
        public TRelatedObject RelatedObject { get; set; }
    }
}

The idea is that you create a quick configuration of the different sort options, what OrderBy expression is used for that, and optionally an object that is related to that sort option. This allows my code to look like:

    protected void InitSortConfig()
    {
        _sortConfig = new SortConfig<xosPodOptimizedSearch, HtmlAnchor>();
        _sortConfig.Add("name", (x => x.LastName), lnkSortName, true);
        _sortConfig.Add("team", (x => x.SchoolName), lnkSortTeam);
        _sortConfig.Add("rate", (x => x.XosRating), lnkSortRate);
        _sortConfig.Add("pos", (x => x.ProjectedPositions), null);
        _sortConfig.Add("height", (x => x.Height), lnkSortHeight);
        _sortConfig.Add("weight", (x => x.Weight), lnkSortWeight);
        _sortConfig.Add("city", (x => x.SchoolCity), lnkSortCity);
        _sortConfig.Add("state", (x => x.SchoolState), lnkSortState);
    }

and then I can sort by just doing

        // Get desired sorting configuration
        InitSortConfig();
        var sortOption = _sortConfig.GetSortOption(sort);
        bool isDescendingSort = sort.EndsWith("desc", StringComparison.OrdinalIgnoreCase);

        // Setup columns
        InitSortLinks();
        if (sortOption.RelatedObject != null)
        {
            // Make modifications to html anchor
        }

        // Form query
        var query = PodDataContext.xosPodOptimizedSearches.AsQueryable();

        if (isDescendingSort)
            query = query.OrderByDescending(sortOption.SortExpression);
        else
            query = query.OrderBy(sortOption.SortExpression);

This works great when the sorted variable is a string, but when it is not a string I get the following exception: Cannot order by type 'System.Object'.

I’m assuming this is because I am storing the expression as Expression<Func<TSource, object>> and not being more specific about that 2nd generic. I don’t understand how I can keep all my different sort options (even for non-string properties) in one class.

I guess one of the issues is that the Linq.OrderBy() clause takes Expression<Func<TSource, TKey>> as it’s parameter, but I am not wrapping my head around how Linq.OrderBy() is able to infer what TKey should be, and therefore I cannot understand how to take advantage of that inference to store these expressions with the proper TKey.

Any ideas?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-03T06:40:09+00:00Added an answer on June 3, 2026 at 6:40 am

    The generic argument is inferred like so:

    IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> enumerable, Func<TSource, TKey> expression)
    

    When you have an IEnumerable<T>, the compiler is able to infer that the TSource is T in this situation because of the extension method declaration; so the extension method is already added on knowing what TSource is. For example:

    Enumerable.Range(0, 10).OrderBy(x => x)
    

    Since we start with an IEnumerable<int>, the compiler can infer that the expression it expects is Func<int, TKey>, because the extension is affecting the IEnumerable<int>. Next, because your expression returns a value, the compiler can infer the remaining type, in this situation int, so it becomes a Func<int, int> with this example.

    Now, germane to your particular problem, you could easily set up your expression to work appropriately if you genericize your SortConfig object appropriately. It looks like your SortConfig takes a Func<TSource, object> delegate right now. If you genericize your SortConfig to use another type, you gain specificity. Example:

     void Add<TSource, TKey>(string name, Func<TSource, TKey> expression)
    

    The next problem here is how to store your backing methods in some format. And your class declaration looks like so:

     public class SortConfig<TSource>
    

    Then all the data types should line up when you invoke the OrderBy extension.

    EDIT: Here’s a working example of what I think you want to do:

        static void Main(string[] args)
        {
            var list = Enumerable.Range(0, 10).Reverse().Select(x => new SampleClass { IntProperty = x, StringProperty = x + "String", DateTimeProperty = DateTime.Now.AddDays(x * -1) });
    
            SortContainer<SampleClass> container = new SortContainer<SampleClass>();
            container.Add("Int", x => x.IntProperty);
            container.Add("String", x => x.StringProperty);
            container.Add("DateTime", x => x.DateTimeProperty);
    
            var sorter = container.GetSorterFor("Int");
    
            sorter.Sort(list).ForEach(x => Console.WriteLine(x.IntProperty));
            Console.ReadKey();
        }
    
        public class SampleClass
        {
            public int IntProperty { get; set; }
            public string StringProperty { get; set; }
            public DateTime DateTimeProperty { get; set; }
        }
    
        public class SortContainer<TSource>
        {
            protected Dictionary<string, ISorter<TSource>> _sortTypes = new Dictionary<string, ISorter<TSource>>();
    
            public void Add<TKey>(string name, Func<TSource, TKey> sortExpression)
            {
                Sorter<TSource, TKey> sorter = new Sorter<TSource, TKey>(sortExpression);
                _sortTypes.Add(name, sorter);
            }
    
            public ISorter<TSource> GetSorterFor(string name)
            {
                return _sortTypes[name];
            }
        }
    
        public class Sorter<TSource, TKey> : ISorter<TSource>
        {
            protected Func<TSource, TKey> _sortExpression = null;
    
            public Sorter(Func<TSource, TKey> sortExpression)
            {
                _sortExpression = sortExpression;
            }
    
            public IOrderedEnumerable<TSource> Sort(IEnumerable<TSource> sourceEnumerable)
            {
                return sourceEnumerable.OrderBy(_sortExpression);
            }
        }
    
        public interface ISorter<TSource>
        {
            IOrderedEnumerable<TSource> Sort(IEnumerable<TSource> sourceEnumerable);
        }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am trying to create a quick hashcode function for a complex number class
I'm trying to make a quick sample Backbone.js app that has a Post model,
I'm trying to create a scrolling button that reacts differently to a quick click
I'm trying to create a Dialog box that will display a video (quick tutorial)
I am trying to use the googlecharts gem to create some quick charts. Here
I'm trying create a bot which automatically likes Facebook posts. Using Mechanize I can
Trying to create a macro which can be used for print debug messages when
Trying to create a generic video plugin for Expression Engine 2 where I can
I am trying to create a quick fix for a problem I am having.
I am trying to create a simple visualization of what my code does. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.