query part breaker.

This commit is contained in:
David Lebée 2018-03-26 20:42:49 -05:00
parent b80e9e433c
commit dcd251f199
5 changed files with 63 additions and 70 deletions

View File

@ -1,4 +1,5 @@
using PoweredSoft.DynamicLinq.Helpers; using PoweredSoft.DynamicLinq.Dal.Pocos;
using PoweredSoft.DynamicLinq.Helpers;
using PoweredSoft.DynamicLinq.Test; using PoweredSoft.DynamicLinq.Test;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -16,16 +17,15 @@ namespace PoweredSoft.DynamicLinq.ConsoleApp
var type = typeof(Dal.Pocos.Author); var type = typeof(Dal.Pocos.Author);
var param = Expression.Parameter(type); var param = Expression.Parameter(type);
var path = "Posts.Comments.Id"; var path = "Posts.Comments.Id";
var expr = ResolveSelectExpression(param, path, SelectCollectionHandling.Flatten);
var expr2 = ResolveSelectExpression(param, path, SelectCollectionHandling.Flatten, true); var parts = ExpressionPathPart.Break(param, "Posts.Comments.Id");
} }
public static Expression ResolveSelectExpression(ParameterExpression param, string path, SelectCollectionHandling selectCollectionHandling = SelectCollectionHandling.LeaveAsIs, bool nullChecking = false)
{
var notCheckNullExpression = QueryablePathHelpers.NavigatePath(param, path, /*
(before, member, isFirst, isLast) => member, * (parent, innerExpression, innerExpressionLambda) =>
(before, member, isFirst, isLast) => member,
(parent, innerExpression, innerExpressionLambda) =>
{ {
var listGenericArgumentType = parent.Type.GetGenericArguments().First(); var listGenericArgumentType = parent.Type.GetGenericArguments().First();
Expression ret = null; Expression ret = null;
@ -36,15 +36,6 @@ namespace PoweredSoft.DynamicLinq.ConsoleApp
return ret; return ret;
} }
); */
if (!nullChecking)
return notCheckNullExpression;
var type = notCheckNullExpression.Type;
throw new NotSupportedException();
}
} }
} }

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace PoweredSoft.DynamicLinq.Helpers
{
public class ExpressionPathPart
{
public Expression ParentExpression { get; set; }
public Expression Expression { get; set; }
public bool IsNullable() => TypeHelpers.IsNullable(Expression.Type);
public bool IsParentParamaterExpression() => ParentExpression is ParameterExpression;
public bool IsGenericEnumerable() => QueryableHelpers.IsGenericEnumerable(Expression);
public Type GenericEnumerableType() => Expression.Type.GenericTypeArguments.First();
public static List<ExpressionPathPart> Break(ParameterExpression param, string path)
{
var ret = new List<ExpressionPathPart>();
var parts = path.Split('.').ToList();
Expression parent = param;
parts.ForEach(part =>
{
var p = new ExpressionPathPart();
p.Expression = Expression.PropertyOrField(parent, part);
p.ParentExpression = parent;
ret.Add(p);
parent = p.IsGenericEnumerable() ? Expression.Parameter(p.GenericEnumerableType()) : p.Expression;
});
return ret;
}
}
}

View File

@ -296,13 +296,11 @@ namespace PoweredSoft.DynamicLinq.Helpers
/// <returns></returns> /// <returns></returns>
public static Expression ResolvePathForExpression(ParameterExpression param, string path) public static Expression ResolvePathForExpression(ParameterExpression param, string path)
{ {
Expression ret = param; var parts = ExpressionPathPart.Break(param, path);
var parts = path.Split('.').ToList(); if (parts.Any(t => t.IsGenericEnumerable()))
parts.ForEach(part => throw new Exception("this method does not support collection handling");
{
ret = Expression.PropertyOrField(ret, part); return parts.Last().Expression;
});
return ret;
} }
public static ConstantExpression GetConstantSameAsLeftOperator(Expression member, object value) public static ConstantExpression GetConstantSameAsLeftOperator(Expression member, object value)

View File

@ -1,53 +1,12 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text; using System.Text;
namespace PoweredSoft.DynamicLinq.Helpers namespace PoweredSoft.DynamicLinq.Helpers
{ {
public static class QueryablePathHelpers public static class QueryablePathHelpers
{ {
public delegate Expression SimplePathNavigated(Expression before, MemberExpression member, bool isFirst, bool isLast);
public delegate Expression CollectionPathNavigated(Expression before, MemberExpression member, bool isFirst, bool isLast);
public delegate Expression CollectionHandling(Expression parent, Expression innerExpression, LambdaExpression innerExpressionLambda);
internal static Expression InternalNavigatePath(Expression before, List<string> parts, SimplePathNavigated simple, CollectionPathNavigated collection, CollectionHandling collectionHandling)
{
var isFirst = before is ParameterExpression;
var isLast = parts.Count() == 1;
var currentExpression = Expression.PropertyOrField(before, parts.First());
var isEnumerable = QueryableHelpers.IsGenericEnumerable(currentExpression);
// allow interaction through callback.
var alteredExpression = isEnumerable ? simple(before, currentExpression, isFirst, isLast) : collection(before, currentExpression, isFirst, isLast);
// if its last we are done :)
if (isLast)
return alteredExpression;
// not enumerable pretty simple.
if (!isEnumerable)
return InternalNavigatePath(alteredExpression, parts.Skip(1).ToList(), simple, collection, collectionHandling);
// enumerable.
var listGenericArgumentType = alteredExpression.Type.GetGenericArguments().First();
// sub param.
var innerParameter = Expression.Parameter(listGenericArgumentType);
var innerExpr = InternalNavigatePath(innerParameter, parts.Skip(1).ToList(), simple, collection, collectionHandling);
var lambda = Expression.Lambda(innerExpr, innerParameter);
var collectionHandlingResult = collectionHandling(alteredExpression, innerExpr, lambda);
return collectionHandlingResult;
}
public static Expression NavigatePath(ParameterExpression param, string path,
SimplePathNavigated simple,
CollectionPathNavigated collection,
CollectionHandling collectionHandling)
{
var parts = path.Split('.').ToList();
return InternalNavigatePath(param, parts, simple, collection, collectionHandling);
}
} }
} }

View File

@ -15,6 +15,15 @@ namespace PoweredSoft.DynamicLinq.Helpers
internal static Lazy<AssemblyBuilder> DynamicAssembly = new Lazy<AssemblyBuilder>(() => AssemblyBuilder.DefineDynamicAssembly(DynamicAssemblyName.Value, AssemblyBuilderAccess.Run)); internal static Lazy<AssemblyBuilder> DynamicAssembly = new Lazy<AssemblyBuilder>(() => AssemblyBuilder.DefineDynamicAssembly(DynamicAssemblyName.Value, AssemblyBuilderAccess.Run));
internal static Lazy<ModuleBuilder> DynamicModule = new Lazy<ModuleBuilder>(() => DynamicAssembly.Value.DefineDynamicModule("PoweredSoft.DynamicLinq.DynamicTypes"));*/ internal static Lazy<ModuleBuilder> DynamicModule = new Lazy<ModuleBuilder>(() => DynamicAssembly.Value.DefineDynamicModule("PoweredSoft.DynamicLinq.DynamicTypes"));*/
public static bool IsNullable(Type type)
{
if (!type.IsValueType)
return true; // ref-type
return Nullable.GetUnderlyingType(type) != null;
}
public static object ConvertFrom(Type type, object source) public static object ConvertFrom(Type type, object source)
{ {
object ret = null; object ret = null;