regular selectables.

This commit is contained in:
David Lebée 2018-03-21 20:00:46 -05:00
parent 3f5433ba53
commit 57fbee664e
5 changed files with 106 additions and 2 deletions

View File

@ -66,6 +66,7 @@
<Compile Include="GroupingTests.cs" />
<Compile Include="Helpers\QueryableAssert.cs" />
<Compile Include="InTests.cs" />
<Compile Include="SelectTests.cs" />
<Compile Include="ShortcutTests.cs" />
<Compile Include="SimpleQueriesTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -0,0 +1,47 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PoweredSoft.DynamicLinq.Dal.Pocos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PoweredSoft.DynamicLinq.Test
{
[TestClass]
public class SelectTests
{
[TestMethod]
public void TestSelect()
{
var regularSyntax = TestData.Authors
.AsQueryable()
.Select(t => new
{
Id = t.Id,
AuthorFirstName = t.FirstName,
AuthorLastName = t.LastName,
Posts = t.Posts.ToList()
}).ToList();
var dynamicSyntax = TestData.Authors
.AsQueryable()
.Select(t =>
{
t.Path("Id");
t.Path("FirstName", "AuthorFirstName");
t.Path("LastName", "AuthorLastName");
t.PathToList("Posts");
}).ToDynamicClassList();
Assert.AreEqual(regularSyntax.Count, dynamicSyntax.Count);
for(var i = 0; i < regularSyntax.Count; i++)
{
Assert.AreEqual(regularSyntax[i].Id, dynamicSyntax[i].GetDynamicPropertyValue<long>("Id"));
Assert.AreEqual(regularSyntax[i].AuthorFirstName, dynamicSyntax[i].GetDynamicPropertyValue<string>("AuthorFirstName"));
Assert.AreEqual(regularSyntax[i].AuthorLastName, dynamicSyntax[i].GetDynamicPropertyValue<string>("AuthorLastName"));
Helpers.QueryableAssert.AreEqual(regularSyntax[i].Posts.AsQueryable(), dynamicSyntax[i].GetDynamicPropertyValue<List<Post>>("Posts").AsQueryable());
}
}
}
}

View File

@ -48,7 +48,9 @@ namespace PoweredSoft.DynamicLinq
LongCount,
Sum,
Average,
ToList
ToList,
PathToList,
Path
}
internal static class Constants

View File

@ -51,6 +51,23 @@ namespace PoweredSoft.DynamicLinq.Fluent
return this;
}
public SelectBuilder Path(string path, string propertyName = null)
{
if (propertyName == null)
propertyName = path.Split('.').LastOrDefault();
throwIfUsedOrEmpty(propertyName);
Parts.Add(new SelectPart
{
Path = path,
PropertyName = propertyName,
SelectType = SelectTypes.Path
});
return this;
}
public SelectBuilder Count(string propertyName)
{
throwIfUsedOrEmpty(propertyName);
@ -116,6 +133,23 @@ namespace PoweredSoft.DynamicLinq.Fluent
return this;
}
public SelectBuilder PathToList(string path, string propertyName = null)
{
if (propertyName == null)
propertyName = path.Split('.').LastOrDefault();
throwIfUsedOrEmpty(propertyName);
Parts.Add(new SelectPart
{
Path = path,
PropertyName = propertyName,
SelectType = SelectTypes.PathToList
});
return this;
}
public virtual IQueryable Build()
{
if (Empty)

View File

@ -196,11 +196,31 @@ namespace PoweredSoft.DynamicLinq.Helpers
private static Expression CreateSelectExpression(IQueryable query, ParameterExpression parameter, SelectTypes selectType, string path)
{
if (!IsGrouping(query))
throw new NotSupportedException("Select without grouping is not supported yet.");
return CreateSelectExpressionRegular(query, parameter, selectType, path);
return CreateSelectExpressionForGrouping(query, parameter, selectType, path);
}
private static Expression CreateSelectExpressionRegular(IQueryable query, ParameterExpression parameter, SelectTypes selectType, string path)
{
if (selectType == SelectTypes.Path)
{
return ResolvePathForExpression(parameter, path);
}
else if (selectType == SelectTypes.PathToList)
{
var expr = ResolvePathForExpression(parameter, path);
var notGroupedType = expr.Type.GenericTypeArguments.FirstOrDefault();
if (notGroupedType == null)
throw new Exception($"Path must be a Enumerable<T> but its a {expr.Type}");
var body = Expression.Call(typeof(Enumerable), "ToList", new[] { notGroupedType }, expr);
return body;
}
throw new NotSupportedException($"unkown select type {selectType}");
}
private static bool IsGrouping(IQueryable query)
{
// TODO needs to be alot better than this, but it will do for now.