我能够获得该书的标题和作者,但未能获得所需的页面标题.
我在行中获得了异常“left11 = Expression.Property(page1,”heading“);”.
我认为我构建的表达式无法识别List.怎么可能这样呢?
请参阅以下代码和stacktrace异常.
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace XMLStorageAndFilter { public class Books { public Books() { Page = new List<Page>(); } public string Title { get; set; } public Author Author { get; set; } public List<Page> Page { get; set; } } public class Author { public string FirstName { get; set; } } public class Page { public string heading { get; set; } } public class Program2 { static void Main() { Page page = new Page(); page.heading = "heading"; Books bok = new Books(); bok.Title = "Title"; bok.Author = new Author() { FirstName = "FirstName" }; bok.Page.Add(page); List<Books> testList = new List<Books>(); testList.Add(bok); IQueryable<Books> queryableTestData = testList.AsQueryable<Books>(); ParameterExpression pe11 = Expression.Parameter(typeof(Books),"p"); Expression left11 = Expression.Property(pe11,"Title"); Expression right11 = Expression.Constant("Title"); Expression e11 = Expression.Equal(left11,right11); var author = Expression.Property(pe11,"Author"); left11 = Expression.Property(author,"FirstName"); right11 = Expression.Constant("FirstName"); Expression e21 = Expression.Equal(left11,right11); Expression predicateBody11 = Expression.And(e11,e21); Expression<Func<Books,bool>> condition = Expression.Lambda <Func<Books,bool>>(predicateBody11,new ParameterExpression[] { pe11 }); var q = queryableTestData.Where(condition); var page1 = Expression.Property(pe11,"Page"); left11 = Expression.Property(page1,"heading"); right11 = Expression.Constant("heading"); Expression e22 = Expression.Equal(left11,right11); Expression predicateBody12 = Expression.And(e11,e22); Expression<Func<Books,bool>> condition2 = Expression.Lambda <Func<Books,bool>>(predicateBody12,new ParameterExpression[] { pe11 }); var qq1 = queryableTestData.Where(condition2); } } }
Exception Message:-
{“Instance property ‘heading’ is not defined for type >’System.Collections.Generic.List`1[XMLStorageAndFilter.Page]'”}StackTrace:-
at System.Linq.Expressions.Expression.Property(Expression expression,String propertyName)
at XMLStorageAndFilter.Program2.Main() in c:\Users\Administrator\Documents\Visual Studio 2013\Projects\XMLStorageAndFilter\NavProperty.cs:line 61
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly,String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state)
at System.Threading.ThreadHelper.ThreadStart()
解决方法
您需要将方法的结果强制转换为Expression< Func< T,bool>>.是你的类型.
我回家后会提供一个完整的例子.
编辑:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Collections; using System.Reflection; namespace ExpressionPredicateBuilder { public enum OperatorComparer { Contains,StartsWith,EndsWith,Equals = ExpressionType.Equal,GreaterThan = ExpressionType.GreaterThan,GreaterThanorEqual = ExpressionType.GreaterThanorEqual,Lessthan = ExpressionType.Lessthan,LessthanorEqual = ExpressionType.Lessthan,NotEqual = ExpressionType.NotEqual } public class ExpressionBuilder { public static Expression<Func<T,bool>> BuildPredicate<T>(object value,OperatorComparer comparer,params string[] properties) { var parameterExpression = Expression.Parameter(typeof(T),typeof(T).Name); return (Expression<Func<T,bool>>)BuildNavigationExpression(parameterExpression,comparer,value,properties); } private static Expression BuildNavigationExpression(Expression parameter,object value,params string[] properties) { Expression resultExpression = null; Expression childParameter,predicate; Type childType = null; if (properties.Count() > 1) { //build path parameter = Expression.Property(parameter,properties[0]); var isCollection = typeof(IEnumerable).IsAssignableFrom(parameter.Type); //if it´s a collection we later need to use the predicate in the methodexpressioncall if (isCollection) { childType = parameter.Type.GetGenericArguments()[0]; childParameter = Expression.Parameter(childType,childType.Name); } else { childParameter = parameter; } //skip current property and get navigation property expression recursivly var innerProperties = properties.Skip(1).ToArray(); predicate = BuildNavigationExpression(childParameter,innerProperties); if (isCollection) { //build subquery resultExpression = BuildSubQuery(parameter,childType,predicate); } else { resultExpression = predicate; } } else { //build final predicate resultExpression = BuildCondition(parameter,properties[0],value); } return resultExpression; } private static Expression BuildSubQuery(Expression parameter,Type childType,Expression predicate) { var anyMethod = typeof(Enumerable).getmethods().Single(m => m.Name == "Any" && m.GetParameters().Length == 2); anyMethod = anyMethod.MakeGenericmethod(childType); predicate = Expression.Call(anyMethod,parameter,predicate); return MakeLambda(parameter,predicate); } private static Expression BuildCondition(Expression parameter,string property,object value) { var childProperty = parameter.Type.GetProperty(property); var left = Expression.Property(parameter,childProperty); var right = Expression.Constant(value); var predicate = BuildComparsion(left,right); return MakeLambda(parameter,predicate); } private static Expression BuildComparsion(Expression left,Expression right) { var mask = new List<OperatorComparer>{ OperatorComparer.Contains,OperatorComparer.StartsWith,OperatorComparer.EndsWith }; if(mask.Contains(comparer) && left.Type != typeof(string)) { comparer = OperatorComparer.Equals; } if(!mask.Contains(comparer)) { return Expression.MakeBinary((ExpressionType)comparer,left,Expression.Convert(right,left.Type)); } return BuildStringCondition(left,right); } private static Expression BuildStringCondition(Expression left,Expression right) { var compareMethod = typeof(string).getmethods().Single(m => m.Name.Equals(Enum.GetName(typeof(OperatorComparer),comparer)) && m.GetParameters().Count() == 1); //we assume ignoreCase,so call ToLower on paramter and memberexpression var toLowerMethod = typeof(string).getmethods().Single(m => m.Name.Equals("ToLower") && m.GetParameters().Count() == 0); left = Expression.Call(left,toLowerMethod); right = Expression.Call(right,toLowerMethod); return Expression.Call(left,compareMethod,right); } private static Expression MakeLambda(Expression parameter,Expression predicate) { var resultParameterVisitor = new ParameterVisitor(); resultParameterVisitor.Visit(parameter); var resultParameter = resultParameterVisitor.Parameter; return Expression.Lambda(predicate,(ParameterExpression)resultParameter); } private class ParameterVisitor : ExpressionVisitor { public Expression Parameter { get; private set; } protected override Expression VisitParameter(ParameterExpression node) { Parameter = node; return node; } } }
}
这可以像
var predicate = ExpressionBuilder.BuildPredicate<Books>("heading",OperatorComparer.Equals,"Page","heading"); query = query.Where(predicate);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。