Revils
Revils

Reputation: 1508

Getting properties from classes within classes in a generic function

This question is a follow-up based on an earlier question: Use a generic method with a list of different type/class

I have the following generic function which looks up properties and sort the list based on the property that has been given as a parameter:

public static void SortList<T>(ref List<T> list, String sortExpression, SortDirection sortDirection) { 
    IList<PropertyInfo> properties = typeof(T).GetProperties();
    foreach(var prop in properties){
        if(prop.Name.Equals(sortExpression)){
            if (sortDirection == SortDirection.Ascending) {
                list.Sort(delegate(T t1, T t2) { return prop.GetValue(t1).ToString().CompareTo(prop.GetValue(t2).ToString()); });
            } else {
                list.Sort(delegate(T t1, T t2) { return prop.GetValue(t2).ToString().CompareTo(prop.GetValue(t1).ToString()); });
            }
            return;
        }
    }
}

This searches all properties of a class and sorts the list based on that property. However, if I have for example a class uitlening which looks as follows:

public class Uitlening {
    public Int64 id { get; set; }
    public Exemplaar exemplaar { get; set; }
    public Medewerker medewerker { get; set; }
    public String van { get; set; }
    public String tot { get; set; }
}

It contains two sub-classes, Exemplaar and Medewerker. My function as is only loops through the properties from Uitlening and not through the properties of Exemplaar and Medewerker.

How can I get the 'sub-properties' from the sub-classes to loop through it and sort my list also based on them?

(I'd like to keep my function generic and not put any class related terms in it; I.E.

if(prop.Name.Equals("Exemplaar") )

Upvotes: 0

Views: 108

Answers (2)

Revils
Revils

Reputation: 1508

I have tried many things and created the following generic method to also sort on subclasses:

    public static void SortList<T>(ref List<T> list, String sortExpression, SortDirection sortDirection) {
        PropertyInfo propertyInfo = typeof(T).GetProperty(sortExpression);
        if (propertyInfo != null) {
            if (sortDirection == SortDirection.Ascending) {
                list.Sort(delegate(T t1, T t2) { return propertyInfo.GetValue(t1).ToString().CompareTo(propertyInfo.GetValue(t2).ToString()); });
            } else {
                list.Sort(delegate(T t1, T t2) { return propertyInfo.GetValue(t2).ToString().CompareTo(propertyInfo.GetValue(t1).ToString()); });
            }
            return;
        } else {
            foreach (var props in typeof(T).GetProperties()) {
                PropertyInfo pro = props.PropertyType.GetProperty(sortExpression);
                if (pro != null) {
                    if (pro.Name.Equals(sortExpression)) {
                        if (sortDirection == SortDirection.Ascending) {
                            list.Sort(delegate(T t1, T t2) {
                                return pro.GetValue(props.GetValue(t1)).ToString().CompareTo(pro.GetValue(props.GetValue(t2)).ToString());
                            });
                        } else {
                            list.Sort(delegate(T t1, T t2) {
                                return pro.GetValue(props.GetValue(t2)).ToString().CompareTo(pro.GetValue(props.GetValue(t1)).ToString());
                            });
                        }
                        return;
                    }
                }
            }
        }
    }

It basically returns when a hit is found, so no unnecessary time is used. First it looks on the first class hierarchy, thereafter it will look on the second hierarchy. (Of course it is now simple to expand to further hierarchy's) I share the answer, for if anybody else might be interested in the answer or anyone has some additional feedback.

Upvotes: 1

arbitrary
arbitrary

Reputation: 103

Create a recursive method that looks at properties, then properties of properties and so on down through the object graph. When it hits on the given property name, it stops recursing and returns the ToString() of the matched property's value.

Then do the sort.

What you are trying to achieve has a potential danger though: you may get an unexpected hit, so though you are trying to make a solution that will work on anything, to be sure it works you need some prior knowledge of the names of the properties all the way down, which means it doesn't really do what you want.

You could tell your recursive method to only recurse on properties of certain types provided in an argument, or those that implement a given interface or inherit from a given base class. In cases where you are sure that you won't get any false positives (on name alone) you could default to object.

Upvotes: 0

Related Questions