selects need to be rethinked.

i'll try to use some kind of path resolve helper which callbacks for each part and allows handling this could be a better idea also will be able to refactor where code to use it as well :)
This commit is contained in:
David Lebée 2018-03-23 19:29:55 -05:00
parent 3fcb34522f
commit 10f15b802c
2 changed files with 34 additions and 16 deletions

View File

@ -57,8 +57,8 @@ namespace PoweredSoft.DynamicLinq.Test
public void MixingInWithCollectionPaths()
{
var titles = new List<string>() { "Match" };
var a = TestData.Authors.AsQueryable().Query(t => t.In("Posts.Title", titles));
var b = TestData.Authors.AsQueryable().Where(t => t.Posts.Any(t2 => titles.Contains(t2.Title)));
var a = TestData.Authors.AsQueryable().Query(t => t.NullChecking(true).In("Posts.Title", titles));
var b = TestData.Authors.AsQueryable().Where(t => t.Posts != null && t.Posts.Any(t2 => titles.Contains(t2.Title)));
QueryableAssert.AreEqual(a, b);
}

View File

@ -150,7 +150,7 @@ namespace PoweredSoft.DynamicLinq.Helpers
{
if (selectType == SelectTypes.Key)
{
return ResolvePathForExpression(parameter, path, selectCollectionHandling);
return ResolvePathForExpression(parameter, path);
}
else if (selectType == SelectTypes.Count)
{
@ -205,11 +205,11 @@ namespace PoweredSoft.DynamicLinq.Helpers
{
if (selectType == SelectTypes.Path)
{
return ResolvePathForExpression(parameter, path, selectCollectionHandling, nullChecking);
return ResolvePathForExpression(parameter, path);
}
else if (selectType == SelectTypes.PathToList)
{
var expr = ResolvePathForExpression(parameter, path, selectCollectionHandling, nullChecking);
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}");
@ -253,7 +253,7 @@ namespace PoweredSoft.DynamicLinq.Helpers
Expression ret = null;
if (!IsEnumerable(memberExpression))
if (!IsGenericEnumerable(memberExpression))
{
// TODO: null checking here too.
// should be easier then collection :=|
@ -276,6 +276,15 @@ namespace PoweredSoft.DynamicLinq.Helpers
ret = Expression.Call(typeof(Enumerable), "SelectMany", new Type[] { listGenericArgumentType, innerExpression.Type.GenericTypeArguments.First() }, memberExpression, lambda);
}
if (step == 1 && nullChecking)
{
ret = Expression.Condition(
Expression.Equal(memberExpression, Expression.Constant(null)),
Expression.New(nullCheckingType),
ret
);
}
return ret;
}
@ -285,14 +294,15 @@ namespace PoweredSoft.DynamicLinq.Helpers
/// <param name="param">Expression.Parameter(typeOfClassOrInterface)</param>
/// <param name="path">the path you wish to resolve example Contact.Profile.FirstName</param>
/// <returns></returns>
public static Expression ResolvePathForExpression(ParameterExpression param, string path, SelectCollectionHandling selectCollectionHandling = SelectCollectionHandling.Select, bool nullChecking = false)
public static Expression ResolvePathForExpression(ParameterExpression param, string path)
{
Expression ret = param;
var parts = path.Split('.').ToList();
var notCheckingNullResult = InternalResolvePathExpression(1, param, parts, selectCollectionHandling, false);
if (!nullChecking)
return notCheckingNullResult;
throw new NotSupportedException("not yet done");
parts.ForEach(part =>
{
ret = Expression.PropertyOrField(ret, part);
});
return ret;
}
public static ConstantExpression GetConstantSameAsLeftOperator(Expression member, object value)
@ -377,7 +387,7 @@ namespace PoweredSoft.DynamicLinq.Helpers
// TODO : maybe support that last part is collection but what do we do?
// not supported yet.
if (isLast && IsEnumerable(memberExpression) && value != null)
if (isLast && IsGenericEnumerable(memberExpression) && value != null)
throw new NotSupportedException("Can only compare collection to null");
@ -402,7 +412,7 @@ namespace PoweredSoft.DynamicLinq.Helpers
if (nullChecking)
nullCheckExpression = Expression.NotEqual(memberExpression, Expression.Constant(null));
if (IsEnumerable(memberExpression))
if (IsGenericEnumerable(memberExpression))
{
var listGenericArgumentType = memberExpression.Type.GetGenericArguments().First();
var innerParameter = Expression.Parameter(listGenericArgumentType, $"t{++recursionStep}");
@ -517,7 +527,15 @@ namespace PoweredSoft.DynamicLinq.Helpers
return result;
}
public static bool IsEnumerable(MemberExpression member) => IsEnumerable(member.Type);
public static bool IsEnumerable(Type type) => typeof(IEnumerable).IsAssignableFrom(type);
public static bool IsGenericEnumerable(MemberExpression member) => IsGenericEnumerable(member.Type);
public static bool IsGenericEnumerable(Type type)
{
if (!type.IsGenericType)
return false;
var genericArgumentType = type.GenericTypeArguments.First();
var ret = typeof(IEnumerable<>).MakeGenericType(genericArgumentType).IsAssignableFrom(type);
return ret;
}
}
}