ready for pull-request.
This commit is contained in:
		
							parent
							
								
									7d9755ef58
								
							
						
					
					
						commit
						a0c59a613a
					
				| @ -7,10 +7,29 @@ using PoweredSoft.DynamicLinq.Helpers; | ||||
| 
 | ||||
| namespace PoweredSoft.DynamicLinq.Test | ||||
| { | ||||
|     class Foo | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     class ListOfFoo : List<Foo> | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     [TestClass] | ||||
|     public class HelpersTests | ||||
|     { | ||||
| 
 | ||||
|         [TestMethod] | ||||
|         public void TestInheritanceOfListAsGenericEnumerableType() | ||||
|         { | ||||
|             var shouldBeTrue = QueryableHelpers.IsGenericEnumerable(typeof(ListOfFoo)); | ||||
|             Assert.IsTrue(shouldBeTrue); | ||||
|             var type = QueryableHelpers.GetTypeOfEnumerable(typeof(ListOfFoo), true); | ||||
|             Assert.IsTrue(type == typeof(Foo)); | ||||
|         } | ||||
| 
 | ||||
|         [TestMethod] | ||||
|         public void TestCreateFilterExpression() | ||||
|         { | ||||
|  | ||||
| @ -23,9 +23,69 @@ namespace PoweredSoft.DynamicLinq.Test | ||||
|         public List<string> FirstNames { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     public class MockPerson | ||||
|     { | ||||
|         public string Name { get; set; } | ||||
|         public MockListOfPhone Phones { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     public class MockPhone | ||||
|     { | ||||
|         public string Number { get; set; } | ||||
|     } | ||||
| 
 | ||||
|     public class MockListOfPhone : List<MockPhone> | ||||
|     { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     [TestClass] | ||||
|     public class SelectTests | ||||
|     { | ||||
|         [TestMethod] | ||||
|         public void TestSelectWithInheritedList() | ||||
|         { | ||||
|             var list = new List<MockPerson>() | ||||
|             { | ||||
|                 new MockPerson | ||||
|                 { | ||||
|                     Name = "David Lebee", | ||||
|                     Phones = new MockListOfPhone | ||||
|                     { | ||||
|                         new MockPhone | ||||
|                         { | ||||
|                             Number = "0000000000" | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|                 new MockPerson | ||||
|                 { | ||||
|                     Name = "Yubing Liang", | ||||
|                     Phones = new MockListOfPhone | ||||
|                     { | ||||
|                         new MockPhone | ||||
|                         { | ||||
|                             Number = "1111111111" | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             var names = list.AsQueryable() | ||||
|                 .Where(t => t.Equal("Phones.Number", "1111111111")) | ||||
|                 .Select(t => | ||||
|                 { | ||||
|                     t.Path("Name"); | ||||
|                     t.FirstOrDefault("Phones.Number", "Number", SelectCollectionHandling.Flatten); | ||||
|                 }) | ||||
|                 .ToDynamicClassList(); | ||||
| 
 | ||||
|             Assert.IsTrue(names.Count() == 1); | ||||
|             var firstPerson = names.First(); | ||||
|             Assert.AreEqual("Yubing Liang", firstPerson.GetDynamicPropertyValue<string>("Name")); | ||||
|             Assert.AreEqual("1111111111", firstPerson.GetDynamicPropertyValue<string>("Number")); | ||||
|         } | ||||
| 
 | ||||
|         [TestMethod] | ||||
|         public void TestSelect() | ||||
|         { | ||||
|  | ||||
| @ -135,9 +135,9 @@ namespace PoweredSoft.DynamicLinq.Test | ||||
|             // subject. | ||||
|             var posts = new List<Post>() | ||||
|             { | ||||
|                 new Post { Id = 1, AuthorId = 1, Title = "Hello 1", Content = "World" }, | ||||
|                 new Post { Id = 2, AuthorId = 1, Title = "Hello 2", Content = "World" }, | ||||
|                 new Post { Id = 3, AuthorId = 2, Title = "Hello 3", Content = "World" }, | ||||
|                 new Post { Id = 1, AuthorId = 1, Title = "Hello 1", Content = "World"}, | ||||
|                 new Post { Id = 2, AuthorId = 1, Title = "Hello 2", Content = "World"}, | ||||
|                 new Post { Id = 3, AuthorId = 2, Title = "Hello 3", Content = "World"}, | ||||
|             }; | ||||
| 
 | ||||
|             // the query. | ||||
| @ -151,5 +151,24 @@ namespace PoweredSoft.DynamicLinq.Test | ||||
|             Assert.IsTrue(first.Id == 3); | ||||
|             Assert.IsTrue(second.Id == 1); | ||||
|         } | ||||
| 
 | ||||
|         [TestMethod] | ||||
|         public void TestingSort2() | ||||
|         { | ||||
|             // subject. | ||||
|             var posts = new List<Post>() | ||||
|             { | ||||
|                 new Post { Id = 1, AuthorId = 1, Title = "Hello 1", Content = "World", Comments = new List<Comment> { }  }, | ||||
|                 new Post { Id = 2, AuthorId = 1, Title = "Hello 2", Content = "World", Comments = new List<Comment> { }  }, | ||||
|                 new Post { Id = 3, AuthorId = 2, Title = "Hello 3", Content = "World", Comments = new List<Comment> { }  }, | ||||
|             }; | ||||
| 
 | ||||
|             // the query. | ||||
|             var query = posts.AsQueryable(); | ||||
|              | ||||
|             // just testing that the expressionm can be created, some drivers support seleting in collections. | ||||
|             var query2 = query.OrderByDescending("Comments"); | ||||
|             var query3 = query.OrderByDescending("Comments.PostId"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -253,7 +253,7 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
| 
 | ||||
|             Expression selectExpression; | ||||
|             if (QueryableHelpers.IsGenericEnumerable(innerSelectType) && selectCollectionHandling == SelectCollectionHandling.Flatten) | ||||
|                 selectExpression = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { selectType, innerSelectType.GenericTypeArguments.First() }, parameter, innerLambdaExpression); | ||||
|                 selectExpression = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { selectType, QueryableHelpers.GetTypeOfEnumerable(innerSelectType, true) }, parameter, innerLambdaExpression); | ||||
|             else | ||||
|                 selectExpression = Expression.Call(typeof(Enumerable), "Select", new Type[] { selectType, innerSelectType }, parameter, innerLambdaExpression); | ||||
| 
 | ||||
| @ -359,7 +359,7 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
|             else | ||||
|             { | ||||
|                 // enumerable. | ||||
|                 var listGenericArgumentType = memberExpression.Type.GetGenericArguments().First(); | ||||
|                 var listGenericArgumentType = QueryableHelpers.GetTypeOfEnumerable(memberExpression.Type, true); | ||||
| 
 | ||||
|                 // sub param. | ||||
|                 var innerParam = Expression.Parameter(listGenericArgumentType); | ||||
| @ -432,7 +432,7 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
|         public static IQueryable CreateOrderByExpression(IQueryable query, string path, QueryOrderByDirection direction, bool append = true) | ||||
|         { | ||||
|             var parameter = Expression.Parameter(query.ElementType, "t"); | ||||
|             var member = QueryableHelpers.ResolvePathForExpression(parameter, path); | ||||
|             var member = QueryableHelpers.ResolvePathForExpression(parameter, path, false); | ||||
| 
 | ||||
|             string sortCommand = null; | ||||
|             if (direction == QueryOrderByDirection.Descending) | ||||
| @ -503,7 +503,7 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
| 
 | ||||
|             if (IsGenericEnumerable(memberExpression)) | ||||
|             { | ||||
|                 var listGenericArgumentType = memberExpression.Type.GetGenericArguments().First(); | ||||
|                 var listGenericArgumentType = QueryableHelpers.GetTypeOfEnumerable(memberExpression.Type, true); | ||||
|                 var innerParameter = Expression.Parameter(listGenericArgumentType, $"t{++recursionStep}"); | ||||
|                 var innerLambda = InternalCreateConditionExpression(recursionStep, listGenericArgumentType, innerParameter, innerParameter, parts.Skip(1).ToList(), condition, value, convertStrategy, collectionHandling, nullChecking, stringComparison, negate); | ||||
| 
 | ||||
| @ -623,12 +623,43 @@ namespace PoweredSoft.DynamicLinq.Helpers | ||||
|         public static bool IsGenericEnumerable(Expression member) => IsGenericEnumerable(member.Type); | ||||
|         public static bool IsGenericEnumerable(Type type) | ||||
|         { | ||||
|             if (!type.IsGenericType) | ||||
|             if (type == typeof(string)) | ||||
|                 return false; | ||||
| 
 | ||||
|             var genericArgumentType = type.GenericTypeArguments.First(); | ||||
|             var ret = typeof(IEnumerable<>).MakeGenericType(genericArgumentType).IsAssignableFrom(type); | ||||
|             return ret; | ||||
|             if (type.IsGenericType) | ||||
|             { | ||||
|                 var makeGenericType = typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments()[0]); | ||||
|                 var possible =  makeGenericType.IsAssignableFrom(type); | ||||
|                 if (possible) | ||||
|                     return true; | ||||
|             } | ||||
|        | ||||
|             var result = type.GetInterfaces().Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)); | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         public static Type GetTypeOfEnumerable(Type genericEnumerableType, bool throwIfNotEnumerable) | ||||
|         { | ||||
|             Type result = null; | ||||
| 
 | ||||
|             if (genericEnumerableType.IsGenericType) | ||||
|             { | ||||
|                 var makeGenericType = typeof(IEnumerable<>).MakeGenericType(genericEnumerableType.GetGenericArguments()[0]); | ||||
|                 var possible = makeGenericType.IsAssignableFrom(genericEnumerableType); | ||||
|                 if (possible) | ||||
|                     return genericEnumerableType.GetGenericArguments()[0]; | ||||
|             } | ||||
| 
 | ||||
|             result = genericEnumerableType.GetInterfaces().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)); | ||||
|             if (result == null) | ||||
|             { | ||||
|                 if (throwIfNotEnumerable) | ||||
|                     throw new Exception("Not a IEnumerable<T>"); | ||||
| 
 | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             return result.GetGenericArguments().First(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -50,7 +50,7 @@ namespace PoweredSoft.DynamicLinq.Parser | ||||
|                 { | ||||
|                     Type = memberExpression.Type, | ||||
|                     IsGenericEnumerable = QueryableHelpers.IsGenericEnumerable(memberExpression), | ||||
|                     EnumerableType = memberExpression.Type.GenericTypeArguments.FirstOrDefault(), | ||||
|                     EnumerableType = QueryableHelpers.GetTypeOfEnumerable(memberExpression.Type, false), | ||||
|                     Parent = parent, | ||||
|                     Name = pp | ||||
|                 }; | ||||
|  | ||||
| @ -74,8 +74,9 @@ namespace PoweredSoft.DynamicLinq.Resolver | ||||
|                     if (isSelectMany) | ||||
|                     { | ||||
|                         var selectType = parent.GroupEnumerableType(); | ||||
|                         var groupExpressionEnumerableType = QueryableHelpers.GetTypeOfEnumerable(groupExpression.Type, true); | ||||
|                         var selectExpression = Expression.Call(typeof(Enumerable), "SelectMany", | ||||
|                             new Type[] { selectType, groupExpression.Type.GenericTypeArguments.First() }, | ||||
|                             new Type[] { selectType, groupExpressionEnumerableType }, | ||||
|                             parentExpression, groupExpressionLambda); | ||||
|                         currentExpression = selectExpression; | ||||
|                     } | ||||
| @ -109,9 +110,10 @@ namespace PoweredSoft.DynamicLinq.Resolver | ||||
| 
 | ||||
|                     if (isSelectMany) | ||||
|                     { | ||||
|                         var currentExpressionEnumerableType = QueryableHelpers.GetTypeOfEnumerable(currentExpression.Type, true); | ||||
|                         var currentExpressionLambda = Expression.Lambda(currentExpression, group.Parameter); | ||||
|                         currentExpression = Expression.Call(typeof(Enumerable), "SelectMany", | ||||
|                             new Type[] { selectType, currentExpression.Type.GenericTypeArguments.First() }, | ||||
|                             new Type[] { selectType, currentExpressionEnumerableType }, | ||||
|                             parentExpression, currentExpressionLambda); | ||||
|                     } | ||||
|                     else | ||||
| @ -144,7 +146,8 @@ namespace PoweredSoft.DynamicLinq.Resolver | ||||
|             Expression ifTrueExpression = null; | ||||
|             if (QueryableHelpers.IsGenericEnumerable(nullType)) | ||||
|             { | ||||
|                 var listType = typeof(List<>).MakeGenericType(nullType.GenericTypeArguments.First()); | ||||
|                 var enumerableType = QueryableHelpers.GetTypeOfEnumerable(nullType, true); | ||||
|                 var listType = typeof(List<>).MakeGenericType(enumerableType); | ||||
|                 ifTrueExpression = Expression.New(listType); | ||||
| 
 | ||||
|             } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user