My solution was to write my own sort-class and add this as a context to nvelocity. I'm passing the field to sort on as string and accessing it as reflection. I'm also setting sort ascending or descending by string value. I'm also passing in the name of the comparer and accessing this with reflection as well. I'm then using the List method OrderBy or OrderByDescending with the choosen field and comparer.
I did find parts of the code here: http://zootfroot.blogspot.co.uk/2009/10/dynamic-linq-orderby.html
public class NvelocitySort
{
public List<MyObject> Sort(List<MyObject> list, string fieldAndMode, string comparerName)
{
fieldAndMode = fieldAndMode.Trim();
// Split the incoming string to get the field name and sort ascending or descending
string[] split = fieldAndMode.Split(' ');
// Set default sort mode
string mode = "asc";
// If sort mode not specified, this will be the field name
string field = fieldAndMode;
// If sort mode added split length shall be 2
if (split.Length == 2)
{
field = split[0];
if (split[1].ToLower() == "asc" || split[1].ToLower() == "ascending") mode = "asc";
if (split[1].ToLower() == "desc" || split[1].ToLower() == "descending") mode = "desc";
}
// If length is more than 2 or 0, return same list as passed in
else if (split.Length > 2 || split.Length == 0)
{
return list;
}
// Get comparer based on comparer name
IComparer<string> comparer = (IComparer<string>)Activator.CreateInstance(Type.GetType(string.Format("Namespace.{0}", comparerName)));
// Choose the sort order
if (mode == "asc")
return list.OrderBy(item => item.GetReflectedPropertyValue(field), comparer).ToList();
if (mode == "desc")
return list.OrderByDescending(item => item.GetReflectedPropertyValue(field), comparer).ToList();
// If sort order not asc/desc return same list as passed in
return list;
}
}
This is the reflection method for retrieving the field.
public static string GetReflectedPropertyValue(this object subject, string field)
{
object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null);
return reflectedValue != null ? reflectedValue.ToString() : "";
}
Simple comparer example:
public class TextComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return string.Compare(x, y);
}
}
Added to Nvelocity context like this:
this.velocityContext.Put("sorter", new NvelocitySort());
Accessed from Nvelocity template like this:
#foreach($item in $sorter.Sort($listObject, "Name desc", "TextComparer"))
$item.Name
#end
Hope it helps someone else...
EDIT: Found an even better way to do it (implements multiple fields sorting): http://www.codeproject.com/Articles/280952/Multiple-Column-Sorting-by-Field-Names-Using-Linq