Skip to content

Commit 90edaa5

Browse files
authored
Add 'np(...)' Null Propagating function (#223)
* GenerateAndAlsoMemberExpression * tests * refactor * 1.0.10 * update test * UserShares
1 parent c8bb7dd commit 90edaa5

File tree

11 files changed

+234
-209
lines changed

11 files changed

+234
-209
lines changed

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
</PropertyGroup>
55

66
<PropertyGroup>
7-
<VersionPrefix>1.0.9.2</VersionPrefix>
7+
<VersionPrefix>1.0.10</VersionPrefix>
88
</PropertyGroup>
99

1010
<Choose>

src-console/ConsoleAppEF2.0.2_InMemory/Program.cs

+22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ namespace ConsoleAppEF2
1111
{
1212
class Program
1313
{
14+
class User
15+
{
16+
public string Name { get; set; }
17+
18+
public string GetDisplayName(bool a, bool b, bool c)
19+
{
20+
return Name + "GetDisplayName";
21+
}
22+
}
23+
1424
class C : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider
1525
{
1626
public HashSet<Type> GetCustomTypes()
@@ -69,6 +79,15 @@ static void Main(string[] args)
6979
};
7080
Console.WriteLine("all {0}", JsonConvert.SerializeObject(all, Formatting.Indented));
7181

82+
var projects = new[]
83+
{
84+
new { UserShares = new [] { new User { Name = "John" } } }
85+
}.AsQueryable();
86+
87+
var filter = "UserShares.Any(GetDisplayName(true,true,false).Contains(\"John\"))";
88+
var filtered = projects.Where(filter);
89+
Console.WriteLine("filtered {0}", JsonConvert.SerializeObject(filtered, Formatting.Indented));
90+
7291
var config = new ParsingConfig
7392
{
7493
CustomTypeProvider = new C()
@@ -83,6 +102,9 @@ static void Main(string[] args)
83102
context.Cars.Add(new Car { Brand = "Alfa", Color = "Black", Vin = "a%bc", Year = "1979", DateLastModified = dateLastModified.AddDays(3) });
84103
context.SaveChanges();
85104

105+
var methodTest = context.Cars.Select("it.X(true, \"tst\").Contains(\"Blue\")");
106+
Console.WriteLine("methodTest {0}", JsonConvert.SerializeObject(methodTest, Formatting.Indented));
107+
86108
var carSingleOrDefault = context.Cars.SingleOrDefault(config, "Brand = \"Ford\"");
87109
Console.WriteLine("carSingleOrDefault {0}", JsonConvert.SerializeObject(carSingleOrDefault, Formatting.Indented));
88110

src-console/ConsoleAppEF2.0/Database/Car.cs

+5
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@ public class Car
2323

2424
[Required]
2525
public DateTime DateLastModified { get; set; }
26+
27+
public string X(bool b, string s)
28+
{
29+
return b + s + Color;
30+
}
2631
}
2732
}

src-console/ConsoleAppEF2.1.1_InMemory/Program.cs

+15-133
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.Reflection;
88
using ConsoleAppEF2.Database;
99
using Newtonsoft.Json;
10-
using Newtonsoft.Json.Linq;
1110

1211
namespace ConsoleAppEF2
1312
{
@@ -18,11 +17,17 @@ public class NestedDto
1817
public string Name { get; set; }
1918

2019
public NestedDto2 NestedDto2 { get; set; }
20+
}
2121

22+
public class NestedDto2
23+
{
24+
public string Name2 { get; set; }
2225

26+
public int Id { get; set; }
27+
public NestedDto3 NestedDto3 { get; set; }
2328
}
2429

25-
public class NestedDto2
30+
public class NestedDto3
2631
{
2732
public string Name2 { get; set; }
2833

@@ -50,129 +55,18 @@ public Type ResolveType(string typeName)
5055
}
5156
}
5257

53-
private static object GetObj()
54-
{
55-
return new
56-
{
57-
Id = 5,
58-
Value = 400
59-
};
60-
}
61-
62-
class X : DynamicClass
63-
{
64-
65-
}
66-
67-
private static IQueryable GetQueryable()
68-
{
69-
var random = new Random((int)DateTime.Now.Ticks);
70-
71-
var jt = typeof(JToken);
72-
73-
var em = jt.GetTypeInfo().GetDeclaredMethods("op_Explicit");
74-
var im = jt.GetTypeInfo().GetDeclaredMethods("op_Explicit");
75-
76-
var j = new JObject
77-
{
78-
{ "Id", new JValue(9) },
79-
{ "Name", new JValue("Test") }
80-
};
81-
82-
//(j["Id"] as JValue).Value
83-
84-
IQueryable jarray = new[] { j }.AsQueryable();
85-
var jresult = jarray.Select("new (int(Id) as Id, string(Name) as Name)");
86-
87-
var an = jresult.Any("Id > 4");
88-
89-
90-
var dx = new X();
91-
dx["Id"] = 5;
92-
93-
IQueryable srcDX = new[] { dx }.AsQueryable();
94-
var b = srcDX.Select("new (Id.ToString() as Id)");
95-
var anyDX = b.Any("int.Parse(Id) > 4");
96-
97-
var x = Enumerable.Range(0, 10).Select(i => new
98-
{
99-
Id = i,
100-
Value = random.Next()
101-
}).AsQueryable();
102-
103-
//var any = x.Any("Id > 4");
104-
105-
//var obj = new
106-
//{
107-
// Id = 5,
108-
// Value = random.Next()
109-
//};
110-
//var x2 = Enumerable.Range(0, 1).Select(_ => obj).AsQueryable();
111-
//var any2 = x.Any("Id > 4");
112-
113-
//var o = GetObj();
114-
//var t = o.GetType();
115-
//IQueryable source = new[] { o }.AsQueryable();
116-
//// source.ElementType = t;
117-
118-
//var x2b = new[] { o }.AsQueryable();
119-
//var any2function = x2b.Any(null, "Id > 4", t);
120-
121-
//var any2b = x2b.Any("Id > 4");
122-
123-
//var x3 = new[] { obj }.AsQueryable();
124-
//var any3 = x3.Any("Id > 4");
125-
126-
return x.Select("new (it as Id, @0 as Value)", random.Next());
127-
// return x.AsQueryable(); //x.AsQueryable().Select("new (Id, Value)");
128-
}
129-
130-
public static IQueryable Transform(this IQueryable source, Type resultType)
58+
static void Main(string[] args)
13159
{
132-
var resultProperties = resultType.GetProperties().Where(p => p.CanWrite);
60+
var q = new[] { new NestedDto(), new NestedDto { NestedDto2 = new NestedDto2 { NestedDto3 = new NestedDto3 { Id = 42 } } } }.AsQueryable();
13361

134-
ParameterExpression s = Expression.Parameter(source.ElementType, "s");
62+
var np1 = q.Select("np(it.NestedDto2.NestedDto3.Id, 0)");
63+
var npResult1 = np1.ToDynamicList<int>();
64+
Console.WriteLine("npResult1 {0}", JsonConvert.SerializeObject(npResult1, Formatting.Indented));
13565

136-
var memberBindings =
137-
resultProperties.Select(p =>
138-
Expression.Bind(resultType.GetMember(p.Name)[0], Expression.Property(s, p.Name))).OfType<MemberBinding>();
66+
var np2 = q.Select("np(it.NestedDto2.NestedDto3.Id)");
67+
var npResult2 = np2.ToDynamicList<int?>();
68+
Console.WriteLine("npResult2 {0}", JsonConvert.SerializeObject(npResult2, Formatting.Indented));
13969

140-
Expression memberInit = Expression.MemberInit(
141-
Expression.New(resultType),
142-
memberBindings
143-
);
144-
145-
var memberInitLambda = Expression.Lambda(memberInit, s);
146-
147-
var typeArgs = new[]
148-
{
149-
source.ElementType,
150-
memberInit.Type
151-
};
152-
153-
var mc = Expression.Call(typeof(Queryable), "Select", typeArgs, source.Expression, memberInitLambda);
154-
155-
var query = source.Provider.CreateQuery(mc);
156-
157-
return query;
158-
}
159-
160-
public static IQueryable<T> EmptyQueryByExample<T>(this T _) => Enumerable.Empty<T>().AsQueryable();
161-
162-
163-
private static TResult Execute<TResult>(MethodInfo operatorMethodInfo, IQueryable source, Expression expression, Type t = null)
164-
{
165-
operatorMethodInfo = operatorMethodInfo.GetGenericArguments().Length == 2
166-
? operatorMethodInfo.MakeGenericMethod(t == null ? source.ElementType : t, typeof(TResult))
167-
: operatorMethodInfo.MakeGenericMethod(t == null ? source.ElementType : t);
168-
169-
var optimized = Expression.Call(null, operatorMethodInfo, source.Expression, expression);
170-
return source.Provider.Execute<TResult>(optimized);
171-
}
172-
173-
static void Main(string[] args)
174-
{
175-
var q = new[] { new NestedDto(), new NestedDto { NestedDto2 = new NestedDto2 { Id = 42 } } }.AsQueryable();
17670
var r1 = q.Select("it != null && it.NestedDto2 != null ? it.NestedDto2.Id : null");
17771
var list1 = r1.ToDynamicList<int?>();
17872

@@ -191,18 +85,6 @@ static void Main(string[] args)
19185
Console.WriteLine(projectedData.First().Name);
19286
Console.WriteLine(projectedData.Last().Name);
19387

194-
IQueryable qry = GetQueryable();
195-
196-
var result = qry.Select("it").OrderBy("Value");
197-
try
198-
{
199-
Console.WriteLine("result {0}", JsonConvert.SerializeObject(result, Formatting.Indented));
200-
}
201-
catch (Exception)
202-
{
203-
// Console.WriteLine(e);
204-
}
205-
20688
var all = new
20789
{
20890
test1 = new List<int> { 1, 2, 3 }.ToDynamicList(typeof(int)),

src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs

+75
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using JetBrains.Annotations;
2+
using System.Collections.Generic;
23
using System.Globalization;
34
using System.Linq.Dynamic.Core.Validation;
45
using System.Linq.Expressions;
@@ -234,5 +235,79 @@ private void WrapConstantExpressions(ref Expression left, ref Expression right)
234235
_constantExpressionWrapper.Wrap(ref right);
235236
}
236237
}
238+
239+
public Expression GenerateAndAlsoNotNullExpression(Expression sourceExpression)
240+
{
241+
var expresssions = CollectExpressions(sourceExpression);
242+
if (!expresssions.Any())
243+
{
244+
return null;
245+
}
246+
247+
// Reverse the list
248+
expresssions.Reverse();
249+
250+
// Convert all expressions into '!= null'
251+
var binaryExpressions = expresssions.Select(expression => Expression.NotEqual(expression, Constants.NullLiteral)).ToArray();
252+
253+
// Convert all binary expressions into `AndAlso(...)`
254+
var andAlsoExpression = binaryExpressions[0];
255+
for (int i = 1; i < binaryExpressions.Length; i++)
256+
{
257+
andAlsoExpression = Expression.AndAlso(andAlsoExpression, binaryExpressions[i]);
258+
}
259+
260+
return andAlsoExpression;
261+
}
262+
263+
private static Expression GetMemberExpression(Expression expression)
264+
{
265+
if (expression is ParameterExpression parameterExpression)
266+
{
267+
return parameterExpression;
268+
}
269+
270+
if (expression is MemberExpression memberExpression)
271+
{
272+
return memberExpression;
273+
}
274+
275+
if (expression is LambdaExpression lambdaExpression)
276+
{
277+
if (lambdaExpression.Body is MemberExpression bodyAsMemberExpression)
278+
{
279+
return bodyAsMemberExpression;
280+
}
281+
282+
if (lambdaExpression.Body is UnaryExpression bodyAsunaryExpression)
283+
{
284+
return bodyAsunaryExpression.Operand;
285+
}
286+
}
287+
288+
return null;
289+
}
290+
291+
private static List<Expression> CollectExpressions(Expression sourceExpression)
292+
{
293+
var list = new List<Expression>();
294+
Expression expression = GetMemberExpression(sourceExpression);
295+
296+
while (expression is MemberExpression memberExpression)
297+
{
298+
expression = GetMemberExpression(memberExpression.Expression);
299+
if (expression is MemberExpression)
300+
{
301+
list.Add(expression);
302+
}
303+
}
304+
305+
if (expression is ParameterExpression)
306+
{
307+
list.Add(expression);
308+
}
309+
310+
return list;
311+
}
237312
}
238313
}

0 commit comments

Comments
 (0)