From 57fbee664e746288516fd9cd722ade2d68102dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Leb=C3=A9e?= Date: Wed, 21 Mar 2018 20:00:46 -0500 Subject: [PATCH] regular selectables. --- .../PoweredSoft.DynamicLinq.Test.csproj | 1 + PoweredSoft.DynamicLinq.Test/SelectTests.cs | 47 +++++++++++++++++++ PoweredSoft.DynamicLinq/Constants.cs | 4 +- .../Fluent/Select/SelectBuilder.cs | 34 ++++++++++++++ .../Helpers/QueryableHelpers.cs | 22 ++++++++- 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 PoweredSoft.DynamicLinq.Test/SelectTests.cs diff --git a/PoweredSoft.DynamicLinq.Test/PoweredSoft.DynamicLinq.Test.csproj b/PoweredSoft.DynamicLinq.Test/PoweredSoft.DynamicLinq.Test.csproj index e2bbfbf..e41965e 100644 --- a/PoweredSoft.DynamicLinq.Test/PoweredSoft.DynamicLinq.Test.csproj +++ b/PoweredSoft.DynamicLinq.Test/PoweredSoft.DynamicLinq.Test.csproj @@ -66,6 +66,7 @@ + diff --git a/PoweredSoft.DynamicLinq.Test/SelectTests.cs b/PoweredSoft.DynamicLinq.Test/SelectTests.cs new file mode 100644 index 0000000..64af1a4 --- /dev/null +++ b/PoweredSoft.DynamicLinq.Test/SelectTests.cs @@ -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("Id")); + Assert.AreEqual(regularSyntax[i].AuthorFirstName, dynamicSyntax[i].GetDynamicPropertyValue("AuthorFirstName")); + Assert.AreEqual(regularSyntax[i].AuthorLastName, dynamicSyntax[i].GetDynamicPropertyValue("AuthorLastName")); + Helpers.QueryableAssert.AreEqual(regularSyntax[i].Posts.AsQueryable(), dynamicSyntax[i].GetDynamicPropertyValue>("Posts").AsQueryable()); + } + } + } +} diff --git a/PoweredSoft.DynamicLinq/Constants.cs b/PoweredSoft.DynamicLinq/Constants.cs index 1d3f4f0..4f6b27f 100644 --- a/PoweredSoft.DynamicLinq/Constants.cs +++ b/PoweredSoft.DynamicLinq/Constants.cs @@ -48,7 +48,9 @@ namespace PoweredSoft.DynamicLinq LongCount, Sum, Average, - ToList + ToList, + PathToList, + Path } internal static class Constants diff --git a/PoweredSoft.DynamicLinq/Fluent/Select/SelectBuilder.cs b/PoweredSoft.DynamicLinq/Fluent/Select/SelectBuilder.cs index 9f6833c..420c7ae 100644 --- a/PoweredSoft.DynamicLinq/Fluent/Select/SelectBuilder.cs +++ b/PoweredSoft.DynamicLinq/Fluent/Select/SelectBuilder.cs @@ -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) diff --git a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs index 128aa15..fcd1a6d 100644 --- a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs +++ b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs @@ -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 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.