Access a Nested Property for a reflection based Comparer

M

MattC

Hi,

I found this code somewhere on the net and need to make some alterations.

public class GenericSorter : IComparer
{
String sortProperty;
bool sortOrder;
public GenericSorter(String sortBy, bool asc)
{
sortProperty = sortBy;
sortOrder = asc;
}
public int Compare(object x, object y)
{
IComparable ic1 =
(IComparable)x.GetType().GetProperty(sortProperty).GetValue(x,null);
IComparable ic2 =
(IComparable)y.GetType().GetProperty(sortProperty).GetValue(y,null);
if(sortOrder)
return ic1.CompareTo(ic2);
else
return ic2.CompareTo(ic1);
}
}

It works fine if the property to sort on is in the current object, for
example ID. However, if I pass sortProperty string such as
"thisDepartment.ID" (in order to sort by the department that the object
belings to).

Is there a way to use GetProperty to evaulate and navigate to the property
in question and then get its value?

So far I have come up with the follwing solutions.

1.) Call GetProperties() and find the first property, search for another '.'
if there isnt one then get the value of the string after the '.'. If there
is another '.' get the propoerties for that property, and so on with
recursion. Bit of a killer in terms of performance, but how else can you
provide the ability to sort on any property in an object model?

2.) Scrap the generic sorter and implement a sort for each property I want
to sort on that does the navigation. requires lots of code.


Any ideas would be cool.

TIA


MattC
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

You have to recurse, find a similar code below with that taken into account

The first if check for a "." in the property used for comparision, if its
found then it meants it's part of a complex member and it simply call it
recursely



int Compare( object x, object y, string comparer)
{
if ( comparer.IndexOf( ".") != -1 )
{
//split the string
string[] parts = comparer.Split( new char[]{ '.'} );
return Compare( x.GetType().GetProperty( parts[0]).GetValue(x, null) ,
y.GetType().GetProperty( parts[0]).GetValue(y, null) , parts[1]
);
}
else
{
IComparable icx, icy;
icx =
(IComparable)x.GetType().GetProperty( comparer).GetValue(x, null);
icy =
(IComparable)y.GetType().GetProperty( comparer).GetValue(y, null);

if ( x.GetType().GetProperty(comparer).PropertyType ==
typeof(System.String) )
{
icx = (IComparable) icx.ToString().ToUpper();
icy = (IComparable) icy.ToString().ToUpper();
}

if(this.sortDirection == SortDirection.Descending)
return icy.CompareTo(icx);
else
return icx.CompareTo(icy);
}

}


cheers,
 
M

MattC

Did this in the end:

public class GenericSorter : IComparer
{
string sortProperty;
bool sortOrder;
string type = String.Empty;

public GenericSorter(String sortBy, bool asc)
{
sortProperty = sortBy;
sortOrder = asc;
}

public int Compare(object x, object y)
{
type = x.ToString();
try
{
return Compare(x,y,sortProperty);
}
catch(Exception e)
{
//throw
}
}

private int Compare(object x, object y, string property)
{
int dotindex = property.IndexOf(".");
//if this string contains a . then this is not the leaf property
if (dotindex != -1 )
{
//split the string
string thisproperty = property.Substring(0,dotindex);//get the string
for this node
string remainder = property.Substring(dotindex+1); //pass the remainder
to recursive call
return Compare( x.GetType().GetProperty(thisproperty).GetValue(x, null),
y.GetType().GetProperty(thisproperty).GetValue(y, null), remainder);
}
else//get the value of the property
{
IComparable ic1 =
(IComparable)x.GetType().GetProperty(property).GetValue(x,null);
IComparable ic2 =
(IComparable)y.GetType().GetProperty(property).GetValue(y,null);

if(sortOrder)
return ic1.CompareTo(ic2);
else
return ic2.CompareTo(ic1);
}
}
}
Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

You have to recurse, find a similar code below with that taken into
account

The first if check for a "." in the property used for comparision, if its
found then it meants it's part of a complex member and it simply call it
recursely



int Compare( object x, object y, string comparer)
{
if ( comparer.IndexOf( ".") != -1 )
{
//split the string
string[] parts = comparer.Split( new char[]{ '.'} );
return Compare( x.GetType().GetProperty( parts[0]).GetValue(x, null) ,
y.GetType().GetProperty( parts[0]).GetValue(y, null) , parts[1]
);
}
else
{
IComparable icx, icy;
icx =
(IComparable)x.GetType().GetProperty( comparer).GetValue(x, null);
icy =
(IComparable)y.GetType().GetProperty( comparer).GetValue(y, null);

if ( x.GetType().GetProperty(comparer).PropertyType ==
typeof(System.String) )
{
icx = (IComparable) icx.ToString().ToUpper();
icy = (IComparable) icy.ToString().ToUpper();
}

if(this.sortDirection == SortDirection.Descending)
return icy.CompareTo(icx);
else
return icx.CompareTo(icy);
}

}


cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


MattC said:
Hi,

I found this code somewhere on the net and need to make some alterations.

public class GenericSorter : IComparer
{
String sortProperty;
bool sortOrder;
public GenericSorter(String sortBy, bool asc)
{
sortProperty = sortBy;
sortOrder = asc;
}
public int Compare(object x, object y)
{
IComparable ic1 =
(IComparable)x.GetType().GetProperty(sortProperty).GetValue(x,null);
IComparable ic2 =
(IComparable)y.GetType().GetProperty(sortProperty).GetValue(y,null);
if(sortOrder)
return ic1.CompareTo(ic2);
else
return ic2.CompareTo(ic1);
}
}

It works fine if the property to sort on is in the current object, for
example ID. However, if I pass sortProperty string such as
"thisDepartment.ID" (in order to sort by the department that the object
belings to).

Is there a way to use GetProperty to evaulate and navigate to the
property in question and then get its value?

So far I have come up with the follwing solutions.

1.) Call GetProperties() and find the first property, search for another
'.' if there isnt one then get the value of the string after the '.'. If
there is another '.' get the propoerties for that property, and so on
with recursion. Bit of a killer in terms of performance, but how else
can you provide the ability to sort on any property in an object model?

2.) Scrap the generic sorter and implement a sort for each property I
want to sort on that does the navigation. requires lots of code.


Any ideas would be cool.

TIA


MattC
 
M

MattC

This works much better, lol

object test = DataBinder.Eval(obj, "property");

Instead of homemade property navigation.

MattC




MattC said:
Did this in the end:

public class GenericSorter : IComparer
{
string sortProperty;
bool sortOrder;
string type = String.Empty;

public GenericSorter(String sortBy, bool asc)
{
sortProperty = sortBy;
sortOrder = asc;
}

public int Compare(object x, object y)
{
type = x.ToString();
try
{
return Compare(x,y,sortProperty);
}
catch(Exception e)
{
//throw
}
}

private int Compare(object x, object y, string property)
{
int dotindex = property.IndexOf(".");
//if this string contains a . then this is not the leaf property
if (dotindex != -1 )
{
//split the string
string thisproperty = property.Substring(0,dotindex);//get the string
for this node
string remainder = property.Substring(dotindex+1); //pass the remainder
to recursive call
return Compare( x.GetType().GetProperty(thisproperty).GetValue(x,
null), y.GetType().GetProperty(thisproperty).GetValue(y, null),
remainder);
}
else//get the value of the property
{
IComparable ic1 =
(IComparable)x.GetType().GetProperty(property).GetValue(x,null);
IComparable ic2 =
(IComparable)y.GetType().GetProperty(property).GetValue(y,null);

if(sortOrder)
return ic1.CompareTo(ic2);
else
return ic2.CompareTo(ic1);
}
}
}
Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

You have to recurse, find a similar code below with that taken into
account

The first if check for a "." in the property used for comparision, if its
found then it meants it's part of a complex member and it simply call it
recursely



int Compare( object x, object y, string comparer)
{
if ( comparer.IndexOf( ".") != -1 )
{
//split the string
string[] parts = comparer.Split( new char[]{ '.'} );
return Compare( x.GetType().GetProperty( parts[0]).GetValue(x, null) ,
y.GetType().GetProperty( parts[0]).GetValue(y, null) , parts[1]
);
}
else
{
IComparable icx, icy;
icx =
(IComparable)x.GetType().GetProperty( comparer).GetValue(x, null);
icy =
(IComparable)y.GetType().GetProperty( comparer).GetValue(y, null);

if ( x.GetType().GetProperty(comparer).PropertyType ==
typeof(System.String) )
{
icx = (IComparable) icx.ToString().ToUpper();
icy = (IComparable) icy.ToString().ToUpper();
}

if(this.sortDirection == SortDirection.Descending)
return icy.CompareTo(icx);
else
return icx.CompareTo(icy);
}

}


cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


MattC said:
Hi,

I found this code somewhere on the net and need to make some
alterations.

public class GenericSorter : IComparer
{
String sortProperty;
bool sortOrder;
public GenericSorter(String sortBy, bool asc)
{
sortProperty = sortBy;
sortOrder = asc;
}
public int Compare(object x, object y)
{
IComparable ic1 =
(IComparable)x.GetType().GetProperty(sortProperty).GetValue(x,null);
IComparable ic2 =
(IComparable)y.GetType().GetProperty(sortProperty).GetValue(y,null);
if(sortOrder)
return ic1.CompareTo(ic2);
else
return ic2.CompareTo(ic1);
}
}

It works fine if the property to sort on is in the current object, for
example ID. However, if I pass sortProperty string such as
"thisDepartment.ID" (in order to sort by the department that the object
belings to).

Is there a way to use GetProperty to evaulate and navigate to the
property in question and then get its value?

So far I have come up with the follwing solutions.

1.) Call GetProperties() and find the first property, search for another
'.' if there isnt one then get the value of the string after the '.'.
If there is another '.' get the propoerties for that property, and so on
with recursion. Bit of a killer in terms of performance, but how else
can you provide the ability to sort on any property in an object model?

2.) Scrap the generic sorter and implement a sort for each property I
want to sort on that does the navigation. requires lots of code.


Any ideas would be cool.

TIA


MattC
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top