reusable methods for diff kind of calls.
This commit is contained in:
		
							parent
							
								
									cbfd55cf02
								
							
						
					
					
						commit
						aba20f04e2
					
				| @ -249,5 +249,83 @@ namespace PoweredSoft.DynamicLinq.Test | ||||
|                 CollectionAssert.AreEqual(expected.Titles as ICollection, titles); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         [TestMethod] | ||||
|         public void GroupByToListWithPath() | ||||
|         { | ||||
|             var limitResult = TestData.Posts.Where(t => t.Author != null); | ||||
| 
 | ||||
|             var expected = limitResult.GroupBy(t => new | ||||
|             { | ||||
|                 AuthorFirstName = t.Author.FirstName | ||||
|             }) | ||||
|             .Select(t => new | ||||
|             { | ||||
|                 Key = t.Key.AuthorFirstName, | ||||
|                 Contents = t.Select(t2 => t2.Content).ToList() | ||||
|             }) | ||||
|             .ToList(); | ||||
| 
 | ||||
|             var actualQuery = limitResult | ||||
|                 .GroupBy(t => t.Path("Author.FirstName", "AuthorFirstName")) | ||||
|                 .Select(t => | ||||
|                 { | ||||
|                     t.Key("Key", "AuthorFirstName"); | ||||
|                     t.ToList("Content", "Contents", SelectCollectionHandling.LeaveAsIs); | ||||
|                 }); | ||||
| 
 | ||||
|             var actual = actualQuery.ToDynamicClassList(); | ||||
| 
 | ||||
|             Assert.AreEqual(expected.Count, actual.Count); | ||||
|             for(var i = 0; i < expected.Count; i++) | ||||
|             { | ||||
|                 var itExpected = expected[i]; | ||||
|                 var itActual = actual[i]; | ||||
| 
 | ||||
| 
 | ||||
|                 Assert.AreEqual(itExpected.Key, itActual.GetDynamicPropertyValue<string>("Key")); | ||||
|                 CollectionAssert.AreEqual(itExpected.Contents, itActual.GetDynamicPropertyValue("Contents") as ICollection); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         [TestMethod] | ||||
|         public void GroupByToListWithPathWithNullChecking() | ||||
|         { | ||||
|             var limitResult = TestData.Authors; | ||||
| 
 | ||||
|             var expected = limitResult.GroupBy(t => new | ||||
|             { | ||||
|                 AuthorFirstName = t.FirstName | ||||
|             }) | ||||
|             .Select(t => new | ||||
|             { | ||||
|                 Key = t.Key.AuthorFirstName, | ||||
|                 Contents = t.SelectMany(t2 => t2.Posts.Select(t3 => t3.Content)).ToList() | ||||
|             }) | ||||
|             .ToList(); | ||||
| 
 | ||||
|             var actualQuery = limitResult | ||||
|                 .GroupBy(t => t.NullChecking().Path("FirstName", "AuthorFirstName")) | ||||
|                 .Select(t => | ||||
|                 { | ||||
|                     t.NullChecking(); | ||||
|                     t.Key("Key", "AuthorFirstName"); | ||||
|                     t.ToList("Posts.Content", "Contents", SelectCollectionHandling.Flatten); | ||||
|                 }); | ||||
| 
 | ||||
|             var actual = actualQuery.ToDynamicClassList(); | ||||
| 
 | ||||
|             Assert.AreEqual(expected.Count, actual.Count); | ||||
|             for (var i = 0; i < expected.Count; i++) | ||||
|             { | ||||
|                 var itExpected = expected[i]; | ||||
|                 var itActual = actual[i]; | ||||
| 
 | ||||
| 
 | ||||
|                 Assert.AreEqual(itExpected.Key, itActual.GetDynamicPropertyValue<string>("Key")); | ||||
|                 CollectionAssert.AreEqual(itExpected.Contents, itActual.GetDynamicPropertyValue("Contents") as ICollection); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -142,7 +142,11 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
|         { | ||||
|             if (selectType == SelectTypes.Key) | ||||
|             { | ||||
|                 return ResolvePathForExpression(parameter, path); | ||||
|                 var parser = new ExpressionParser(parameter, path); | ||||
|                 var resolver = new PathExpressionResolver(parser); | ||||
|                 resolver.NullChecking = nullChecking; | ||||
|                 resolver.Resolve(); | ||||
|                 return resolver.GetResultBodyExpression(); | ||||
|             } | ||||
|             else if (selectType == SelectTypes.Count) | ||||
|             { | ||||
| @ -157,76 +161,69 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
|                 return body; | ||||
|             } | ||||
|             else if (selectType == SelectTypes.Average) | ||||
|             { | ||||
|                 /// https://stackoverflow.com/questions/25482097/call-enumerable-average-via-expression | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var innerParameter = Expression.Parameter(notGroupedType); | ||||
|                 var innerMemberExpression = ResolvePathForExpression(innerParameter, path); | ||||
|                 var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); | ||||
|                 var body = Expression.Call(typeof(Enumerable), "Average", new[] { notGroupedType }, parameter, innerMemberLambda); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedAggregateExpression(parameter, path, "Average"); | ||||
|             else if (selectType == SelectTypes.Sum) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var innerParameter = Expression.Parameter(notGroupedType); | ||||
|                 var innerMemberExpression = ResolvePathForExpression(innerParameter, path); | ||||
|                 var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); | ||||
|                 var body = Expression.Call(typeof(Enumerable), "Sum", new[] { notGroupedType }, parameter, innerMemberLambda); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedAggregateExpression(parameter, path, "Sum"); | ||||
|             else if (selectType == SelectTypes.Min) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var innerParameter = Expression.Parameter(notGroupedType); | ||||
|                 var innerMemberExpression = ResolvePathForExpression(innerParameter, path); | ||||
|                 var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); | ||||
|                 var body = Expression.Call(typeof(Enumerable), "Min", new[] { notGroupedType }, parameter, innerMemberLambda); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedAggregateExpression(parameter, path, "Min"); | ||||
|             else if (selectType == SelectTypes.Max) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var innerParameter = Expression.Parameter(notGroupedType); | ||||
|                 var innerMemberExpression = ResolvePathForExpression(innerParameter, path); | ||||
|                 var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); | ||||
|                 var body = Expression.Call(typeof(Enumerable), "Max", new[] { notGroupedType }, parameter, innerMemberLambda); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedAggregateExpression(parameter, path, "Max"); | ||||
|             else if (selectType == SelectTypes.ToList) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var body = Expression.Call(typeof(Enumerable), "ToList", new[] { notGroupedType }, parameter); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedPathExpressionWithMethod(parameter, path, selectCollectionHandling, nullChecking, "ToList"); | ||||
|             else if (selectType == SelectTypes.First) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var body = Expression.Call(typeof(Enumerable), "First", new[] { notGroupedType }, parameter); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedPathExpressionWithMethod(parameter, path, selectCollectionHandling, nullChecking, "First"); | ||||
|             else if (selectType == SelectTypes.Last) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var body = Expression.Call(typeof(Enumerable), "Last", new[] { notGroupedType }, parameter); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedPathExpressionWithMethod(parameter, path, selectCollectionHandling, nullChecking, "Last"); | ||||
|             else if (selectType == SelectTypes.FirstOrDefault) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var body = Expression.Call(typeof(Enumerable), "FirstOrDefault", new[] { notGroupedType }, parameter); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedPathExpressionWithMethod(parameter, path, selectCollectionHandling, nullChecking, "FirstOrDefault"); | ||||
|             else if (selectType == SelectTypes.LastOrDefault) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var body = Expression.Call(typeof(Enumerable), "LastOrDefault", new[] { notGroupedType }, parameter); | ||||
|                 return body; | ||||
|             } | ||||
|                 return CreateGroupedPathExpressionWithMethod(parameter, path, selectCollectionHandling, nullChecking, "LastOrDefault"); | ||||
| 
 | ||||
|             throw new NotSupportedException($"unkown select type {selectType}"); | ||||
|         } | ||||
| 
 | ||||
|         private static Expression CreateGroupedAggregateExpression(ParameterExpression parameter, string path, string methodName) | ||||
|         { | ||||
|             /// https://stackoverflow.com/questions/25482097/call-enumerable-average-via-expression | ||||
|             var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|             var innerParameter = Expression.Parameter(notGroupedType); | ||||
|             var innerMemberExpression = ResolvePathForExpression(innerParameter, path); | ||||
|             var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); | ||||
|             var body = Expression.Call(typeof(Enumerable), methodName, new[] { notGroupedType }, parameter, innerMemberLambda); | ||||
|             return body; | ||||
|         } | ||||
| 
 | ||||
|         private static Expression CreateGroupedPathExpressionWithMethod(ParameterExpression parameter, string path, SelectCollectionHandling selectCollectionHandling, bool nullChecking, string methodName) | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(path)) | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var body = Expression.Call(typeof(Enumerable), methodName, new[] { notGroupedType }, parameter); | ||||
|                 return body; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 var notGroupedType = parameter.Type.GenericTypeArguments[1]; | ||||
|                 var innerParameter = Expression.Parameter(notGroupedType); | ||||
|                 var parser = new ExpressionParser(innerParameter, path); | ||||
|                 var resolver = new PathExpressionResolver(parser); | ||||
|                 resolver.NullChecking = nullChecking; | ||||
|                 resolver.Resolve(); | ||||
|                 var expression = resolver.Result; | ||||
|                 var selectExpression = WrapIntoSelectFromGrouping(parameter, expression, selectCollectionHandling); | ||||
|                 var body = CallMethodOnSelectExpression(methodName, selectExpression); | ||||
|                 return body; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private static Expression WrapIntoSelectFromGrouping(ParameterExpression parameter, Expression innerLambdaExpression, SelectCollectionHandling selectCollectionHandling) | ||||
|         { | ||||
|             var selectType = parameter.Type.GenericTypeArguments.Skip(1).First(); | ||||
|             var innerSelectType = ((LambdaExpression)innerLambdaExpression).ReturnType; | ||||
|             var selectExpression = Expression.Call(typeof(Enumerable), "Select", new Type[] { selectType, innerSelectType }, parameter, innerLambdaExpression); | ||||
|             return selectExpression; | ||||
|         } | ||||
| 
 | ||||
|         private static Expression CreateSelectExpression(IQueryable query, ParameterExpression parameter, SelectTypes selectType, string path, SelectCollectionHandling selectCollectionHandling, bool nullChecking) | ||||
|         { | ||||
|             if (!IsGrouping(query)) | ||||
| @ -277,6 +274,13 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
|             return body; | ||||
|         } | ||||
| 
 | ||||
|         private static Expression CallMethodOnSelectExpression(string methodName, Expression selectExpression) | ||||
|         { | ||||
|             var notGroupedType = selectExpression.Type.GenericTypeArguments.First(); | ||||
|             var body = Expression.Call(typeof(Enumerable), methodName, new[] { notGroupedType }, selectExpression) as Expression; | ||||
|             return body; | ||||
|         } | ||||
| 
 | ||||
|         private static bool IsGrouping(IQueryable query) | ||||
|         { | ||||
|             // TODO needs to be alot better than this, but it will do for now. | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user