Click here to Skip to main content
12,623,724 members (33,524 online)
Rate this:
 
Please Sign up or sign in to vote.
See more: C# .NET WPF LINQ collections .NET4 , +
Background to problem: I have a
BindingList<T>
of dynamic objects. These objects are of some type of class which is created at runtime. This class can have 1 or 2 or 3 or more properties. Names of these properties can also be different everytime when this class is created.
e.g.
Class Data
{
Property Value1;
Property Value2;
Property Value3;
..
...
}

Next time this class can be
Class Data
{
Property Value1;
Property Value2;
}

Issue is: Based on some parameter I can get a value from user 'Value1'. Then I want to sort this list of dynamic objects on value of property 'Value1'.
Posted 23-Jan-13 18:41pm

1 solution

Rate this: bad
 
good
Please Sign up or sign in to vote.

Solution 1

You need to implement a Comparer[^], and pass it to the List.Sort[^] method.
But since you have dynamic objects, you need to use reflection to get the values. Use this[^] approach:

public class DynamicSerializableComparer : IComparer<object>
{
    string _property;
 
    public DynamicSerializableComparer(string property)
    {
        _property = property;
    }
 
    public int Compare(object stringA, object stringB)
    {
        string valueA = stringA.GetType().GetProperty(_property).GetValue();
        string valueB = stringB.GetType().GetProperty(_property).GetValue();
 
        return String.Compare(valueA, valueB);
    }
 
}
Of course, if the property you have is not string or not comparable as string, you should change the last statement accordingly.

[Update: some improvements, and a sample]
As I mentioned, you can't use OrderBy, since there is no property you can specify in the lambda expression.

public class DynamicSerializableComparer : IComparer<object>
{
    string _property;
 
    public DynamicSerializableComparer(string property)
    {
        _property = property;
    }
 
    public int Compare(object stringA, object stringB)
    {
        string valueA = (string)stringA.GetType().GetProperty(_property).GetValue(stringA, null);
        string valueB = (string)stringB.GetType().GetProperty(_property).GetValue(stringB, null);
 
        return String.Compare(valueA, valueB);
    }
}
 
void Main()
{
    var a1 = new { id = 1, name="Peter", email="a@x.com"};
    var a2 = new { id = 2, name="John", address="USA"};
    var a3 = new { id = 3, name="Robert", address="France"};
    var a4 = new { id = 4, name="Albert", position="Boss"};
 
    var a = new List<object> {a1, a2, a3, a4};
 
    a.Sort(new DynamicSerializableComparer("name"));
 
    a.Dump();
}

This sample will run directly in LinqPad[^] (I suggest you download it if you don't have it already, it is a must if you develop linq stuff...), but you can write a simple dumper or inspect the sorted list in VS. As you can see, there is not even a class defined, all objects are inline. Won't work if you change the constructor parameter to a property that's not common in all objects - in such case you have to decide and add logic to the comparer how to compare nonexistent properties. But you can use this sample to implement a comparer for your needs.
  Permalink  
v3
Comments
Pranav_Parashar 24-Jan-13 3:53am
   
I ge ta complie time error: The type arguments for method 'System.Linq.Enumerable.OrderBy<tsource,tkey>(System.Collections.Generic.IEnumerable<tsource>, System.Func<tsource,tkey>, System.Collections.Generic.IComparer<tkey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Maybe this is because of the dynamic class that I am creating at runtime
Zoltán Zörgő 24-Jan-13 12:38pm
   
No. OrderBy makes no sense in this context, since you can not reference a dynamic property at compile time in the lambda expression. You have to use Sort. I will post a more complex sample shortly.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


Advertise | Privacy | Mobile
Web02 | 2.8.161128.1 | Last Updated 24 Jan 2013
Copyright © CodeProject, 1999-2016
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100