按匿名类型声明中的财产索引排序

时间:2015-03-20 16:46:45

标签: c# linq

我有一个复杂的问题,没有太多细节。我只是想知道这是否可能。

我有一个Ordered Linq查询,它获取数据的子集并将其推送到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();

根据匿名类型声明的索引对此进行排序是否可能?

0 => ItemNumber
1 => Name
2 => MasterEdited

我需要能够在明确声明要对列名进行排序的情况下执行此操作,因此这对于任何匿名类型都可以通用。

2 个答案:

答案 0 :(得分:2)

是和否。您不能直接执行此操作,并且不会对匿名类型(或任何对象)的属性/字段编制索引。因此,您无法使用索引来访问这些属性。

据说可以使用反射来访问没有名字的数据。

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]);

上面的代码创建了一个可以使用索引的属性数组,尽管您不知道这些属性实际上是什么。然后,您可以循环遍历PropertyInfo个对象的数组,并调用propInfo.GetValue(anonObject);以返回匿名对象中该属性中存储的值。

如果您想从PropertyInfo对象中获取属性的名称,只需拨打propInfo.Name即可。

答案 1 :(得分:0)

我希望这还不算太晚,但我有一些工作代码供你使用。我以前在一个项目中使用过它,并没有引起任何注意到的问题。

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;
}