Reputation:
I have a complex problem, without going into too many details. I'm just wondering if this is possible.
I have an Ordered Linq query which gets a subset of data and pushes it into a DataTable.
var FormattedDataSet = DataSet.Select(t => new
{
ItemNumber = t.ExtTitleID,
Name = "<a href='/Title/Preview/" + t.ID + "'>" + t.TitleFullName + "</a>",
Master_Edited = t.MediaDetails.FirstOrDefault().Datecaptured
}).ToList();
Is it Possible Int to sort this based on the index of the declaration of the Anonymous Type?
0 => ItemNumber
1 => Name
2 => MasterEdited
I need to be able to do this with out explicitly declaring the column name to sort by, so this can work generically for any anonymous type.
Upvotes: 1
Views: 1373
Reputation: 21005
I hope this is not too late but I have some working code for you. I've used this in a project before and it hasn't caused any noticed problems.
public static IOrderedQueryable<T> OrderByPropertyDeclarionIndex<T>(this IQueryable<T> source, int propertyIndex, bool isDescending = false)
{
string OrderByText = isDescending ? "OrderByDescending" : "OrderBy";
return ApplyOrder(source, propertyIndex, OrderByText);
}
private static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, int property, string methodName)
{
var type = typeof(T);
var arg = Expression.Parameter(type, "x");
Expression expr = arg;
var propertyinfos = type.GetProperties();
var pi = propertyinfos[property];
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
var delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
var lambda = Expression.Lambda(delegateType, expr, arg);
var result = typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable<T>)result;
}
Upvotes: 0
Reputation: 7097
Yes and no. You cannot do this directly and properties/fields of anonymous types (or any object) are not indexed. Therefore you cannot use an index to access those properties.
With that being said you can use reflection to access the data without their names.
var FormattedDataSet = /*linq query to create list of anon types*/
//we only need to analyze one of them since all items in the list should be of the same type
Type t = formattedDataSet[0].GetType();
PropertyInfo[] pi = t.GetProperties();
//get value of "property one" of the first anon object in your list
object data = pi[0].GetValue(FormattedDataSet[0]);
The above code creates an array of properties that you can use an index on, although you won't know what the properties actually are. You can then loop through the array of PropertyInfo
objects and call propInfo.GetValue(anonObject);
to return the value stored in that property in the anonymous object.
If you want to get the name of a property out of the PropertyInfo
object you can just call propInfo.Name
.
Upvotes: 2