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