从OrderBy中使用的方法返回表达式
我想编写一个由子类重写的抽象方法,该方法的作用是返回一个表达式,以便随后在LINQ OrderBy()
。 像这样的东西:
注意: Message
inheritance自Notes
类, MyModel
inheritance自MsgModel
。
public class Notes { // abstract definition; using object so that I can (I hope) order by int, string, etc. public abstract Expression<Func> OrderByField(); // ... private string GetOrderByFieldName() { // I am not sure how to write this // This is my problem 2. Please see below for problem 1 :-( var lambda = OrderByField() as LambdaExpression; MemberExpression member = lambda.Body as MemberExpression; PropertyInfo propInfo = member.Member as PropertyInfo; return propInfo.Name; } } public class Message : Notes { // second type parameter is object because I don't know the type // of the orderby field beforehand public override Expression<Func> OrderByField() { return m => m.item_no; } }
现在,如果我尝试通过这种方式订购:
var orderedQuery = myQueryable.OrderBy(OrderByField());
我收到此错误:
‘无法将类型’System.Int32’强制转换为’System.Object’。 LINQ to Entities仅支持转换EDM原语或枚举类型。
我可以马上说,类型参数对象是问题的原因。 因此,当我将type参数更改为int时,只要我按int字段(例如字段item_no
)排序,它就可以正常工作。
Q1。 我怎样才能让它发挥作用? 当然,我可以使用字符串属性OrderByField
而不是表达式返回方法和它的顺序,可能是通过为IQueryable编写一些扩展方法(也许使用这个很棒的答案 )。 但是我希望在设置顺序时有更多智能感知。
Q2。 如何从OrderByField()
方法返回的表达式中获取列的名称。 显然我尝试过的东西不起作用。 该member
始终为null。
编辑:我对方法的类型参数进行了一些更改。 很抱歉没有第一次这样做。
显然, Expression
不等同于Expression
,因此不能用作Queryable.OrderBy
和类似方法所要求的后者的直接替换。
通过Expression.Lambda
方法创建非通用LambdaExpression
并动态发出对相应Queryable
方法的调用,仍然可以在Expression
类的帮助下使其工作。
以下是自定义扩展方法中封装的所有内容(我对如何使用字符串通过表达式创建EF顺序的答案的修改版本? ):
public static partial class QueryableExtensions { public static IOrderedQueryable OrderBy (this IQueryable source, Expression> keySelector) { return source.OrderBy(keySelector, "OrderBy"); } public static IOrderedQueryable OrderByDescending (this IQueryable source, Expression> keySelector) { return source.OrderBy(keySelector, "OrderByDescending"); } public static IOrderedQueryable ThenBy (this IOrderedQueryable source, Expression> keySelector) { return source.OrderBy(keySelector, "ThenBy"); } public static IOrderedQueryable ThenByDescending (this IOrderedQueryable source, Expression> keySelector) { return source.OrderBy(keySelector, "ThenByDescending"); } private static IOrderedQueryable OrderBy (this IQueryable source, Expression> keySelector, string method) { var parameter = keySelector.Parameters[0]; var body = keySelector.Body; if (body.NodeType == ExpressionType.Convert) body = ((UnaryExpression)body).Operand; var selector = Expression.Lambda(body, parameter); var methodCall = Expression.Call( typeof(Queryable), method, new[] { parameter.Type, body.Type }, source.Expression, Expression.Quote(selector)); return (IOrderedQueryable )source.Provider.CreateQuery(methodCall); } }
这里的一个重要细节是Expression
为表达式返回表达式引入了Expression.Convert
,因此需要从实际的lambda 体中去掉它,这是通过以下代码部分完成的:
var body = keySelector.Body; if (body.NodeType == ExpressionType.Convert) body = ((UnaryExpression)body).Operand;
Notes
类需要几种generics类型。 第一个是因此你可以从它派生并仍然允许表达式过滤派生类。 第二种是指定您希望用于订购的财产的类型。 例如:
public abstract class Notes where T : Notes { public abstract Expression> OrderByField(); public string GetOrderByFieldName() { //snip } } public class Message : Notes { public int item_no { get; set; } public override Expression> OrderByField() { return m => m.item_no; } }
这也应该允许GetOrderByFieldName
方法工作。
这是一个(几乎)不使用reflection或表达式的解决方案:它利用了排序LINQ函数在其结果中只有一个generics类型的事实。
1,创建一个接口(只有一个通用参数)和一个实现(带有两个通用参数):
public interface ISortCrit { string SortFieldName { get; } IOrderedEnumerable MakeOrderBy(IEnumerable source); IOrderedEnumerable MakeOrderByDescending(IEnumerable source); IOrderedEnumerable MakeThenBy(IOrderedEnumerable source); IOrderedEnumerable MakeThenByDescending(IOrderedEnumerable source); IOrderedQueryable MakeOrderBy(IQueryable source); IOrderedQueryable MakeOrderByDescending(IQueryable source); IOrderedQueryable MakeThenBy(IOrderedQueryable source); IOrderedQueryable MakeThenByDescending(IOrderedQueryable source); } public class SortCrit : ISortCrit { private readonly Expression> _sortExpression; private readonly Lazy> _sortDelegate; private readonly Lazy _sortFieldName; public SortCrit(Expression> sortExpression) { _sortExpression = sortExpression; _sortDelegate = new Lazy>(() => sortExpression.Compile()); _sortFieldName = new Lazy (() => ((MemberExpression)sortExpression.Body).Member.Name); } public string SortFieldName => _sortFieldName.Value; public IOrderedEnumerable MakeOrderBy(IEnumerable source) => source.OrderBy(_sortDelegate.Value); public IOrderedEnumerable MakeOrderByDescending(IEnumerable source) => source.OrderByDescending(_sortDelegate.Value); public IOrderedEnumerable MakeThenBy(IOrderedEnumerable source) => source.ThenBy(_sortDelegate.Value); public IOrderedEnumerable MakeThenByDescending(IOrderedEnumerable source) => source.ThenBy(_sortDelegate.Value); public IOrderedQueryable MakeOrderBy(IQueryable source) => source.OrderBy(_sortExpression); public IOrderedQueryable MakeOrderByDescending(IQueryable source) => source.OrderByDescending(_sortExpression); public IOrderedQueryable MakeThenBy(IOrderedQueryable source) => source.ThenBy(_sortExpression); public IOrderedQueryable MakeThenByDescending(IOrderedQueryable source) => source.ThenByDescending(_sortExpression); }
第二部分会议扩展:
public static class SortCrit { public static ISortCrit Create(Expression> sortExpression) => new SortCrit(sortExpression); public static IOrderedEnumerable OrderBy (this IEnumerable source, ISortCrit crit) => crit.MakeOrderBy(source); public static IOrderedEnumerable OrderByDescending (this IEnumerable source, ISortCrit crit) => crit.MakeOrderByDescending(source); public static IOrderedEnumerable ThenBy (this IOrderedEnumerable source, ISortCrit crit) => crit.MakeThenBy(source); public static IOrderedEnumerable ThenByDescending (this IOrderedEnumerable source, ISortCrit crit) => crit.MakeThenByDescending(source); public static IOrderedQueryable OrderBy (this IQueryable source, ISortCrit crit) => crit.MakeOrderBy(source); public static IOrderedQueryable OrderByDescending (this IQueryable source, ISortCrit crit) => crit.MakeOrderByDescending(source); public static IOrderedQueryable ThenBy (this IOrderedQueryable source, ISortCrit crit) => crit.MakeThenBy(source); public static IOrderedQueryable ThenByDescending (this IOrderedQueryable source, ISortCrit crit) => crit.MakeThenByDescending(source); }
用法:
上述就是C#学习教程:从OrderBy中使用的方法返回表达式分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
var messageCrit = SortCrit.Create((Message m) => m.ItemNo); IEnumerable msgs = ...; msgs.OrderBy(messageCrit);
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/991368.html