Skip to content

Commit 90b1ddf

Browse files
Add ContainsKey features for issue: #384
1 parent 4975c26 commit 90b1ddf

File tree

5 files changed

+152
-2
lines changed

5 files changed

+152
-2
lines changed

Z.Dynamic.Core.Lab/Program.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Program
66
{
77
static void Main(string[] args)
88
{
9-
Request_GroupBy_IEqualityComparer.Execute();
10-
}
9+
Request_AddMethod.Execute();
10+
}
1111
}
1212
}
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Linq.Dynamic.Core;
6+
using System.Linq.Dynamic.Core.Parser;
7+
using System.Linq.Expressions;
8+
using System.Text;
9+
10+
namespace Z.Dynamic.Core.Lab
11+
{
12+
class Request_AddMethod
13+
{
14+
public class Customer
15+
{
16+
public string City { get; set; }
17+
public Dictionary<string, Order> Orders { get; set; }
18+
public string CompanyName { get; set; }
19+
public string Phone { get; set; }
20+
}
21+
public class Order
22+
{
23+
}
24+
25+
public static void Execute()
26+
{
27+
List<Customer> customers = new List<Customer>()
28+
{
29+
new Customer() { City = "ZZZ1", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() },
30+
new Customer() { City = "ZZZ2", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() },
31+
new Customer() { City = "ZZZ3", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() }
32+
};
33+
customers.ForEach(x => x.Orders.Add(x.City + "TEST", new Order()));
34+
35+
36+
37+
var query = customers.AsQueryable()
38+
.Where("Orders.ContainsKey(\"ZZZ2TEST\")", "ZZZ", 1)
39+
.OrderBy("CompanyName")
40+
.Select("new(City as City, Phone)").ToDynamicList();
41+
42+
43+
44+
45+
var data = customers.AsQueryable()
46+
.Where("Orders.ContainsKey(it.City + \"TEST\")")
47+
.OrderBy("City")
48+
.Select("new(City as City, Phone)").ToDynamicList();
49+
}
50+
}
51+
}

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

+25
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,15 @@ Expression ParseMemberAccess(Type type, Expression instance)
16161616
{
16171617
if (instance != null && type != typeof(string))
16181618
{
1619+
Type dictionaryType = TypeHelper.FindGenericType(typeof(IDictionary<,>), type);
1620+
if (dictionaryType != null)
1621+
{
1622+
if(TryParseDictionary(instance, id, type, out var expression))
1623+
{
1624+
return expression;
1625+
}
1626+
}
1627+
16191628
Type enumerableType = TypeHelper.FindGenericType(typeof(IEnumerable<>), type);
16201629
if (enumerableType != null)
16211630
{
@@ -1716,6 +1725,22 @@ Expression ParseMemberAccess(Type type, Expression instance)
17161725
throw ParseError(errorPos, Res.UnknownPropertyOrField, id, TypeHelper.GetTypeName(type));
17171726
}
17181727

1728+
bool TryParseDictionary(Expression instance, string methodName, Type type, out Expression expression)
1729+
{
1730+
expression = null;
1731+
1732+
Expression[] args = ParseArgumentList();
1733+
1734+
if (!_methodFinder.ContainsMethod(typeof(IDictionarySignatures), methodName, false, args))
1735+
{
1736+
return false;
1737+
}
1738+
1739+
var method = type.GetMethod(methodName);
1740+
expression = Expression.Call(instance, method, args);
1741+
return true;
1742+
}
1743+
17191744
Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos, bool isQueryable)
17201745
{
17211746
var oldParent = _parent;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace System.Linq.Dynamic.Core.Parser.SupportedMethods
2+
{
3+
internal interface IDictionarySignatures
4+
{
5+
void ContainsKey(object selector);
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using NFluent;
7+
using Xunit;
8+
9+
namespace System.Linq.Dynamic.Core.Tests.MikArea
10+
{
11+
public class Dictionary
12+
{
13+
public class Customer
14+
{
15+
public string City { get; set; }
16+
public Dictionary<string, Order> Orders { get; set; }
17+
public string CompanyName { get; set; }
18+
public string Phone { get; set; }
19+
}
20+
public class Order
21+
{
22+
}
23+
24+
[Fact]
25+
public void Test_ContainsKey_1()
26+
{
27+
List<Customer> customers = new List<Customer>()
28+
{
29+
new Customer() { City = "ZZZ1", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() },
30+
new Customer() { City = "ZZZ2", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() },
31+
new Customer() { City = "ZZZ3", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() }
32+
};
33+
customers.ForEach(x => x.Orders.Add(x.City + "TEST", new Order()));
34+
35+
36+
37+
var data = customers.AsQueryable()
38+
.Where("Orders.ContainsKey(\"ZZZ2TEST\")")
39+
.OrderBy("CompanyName")
40+
.Select("new(City as City, Phone)").ToDynamicList();
41+
42+
Check.That("ZZZ2").IsEqualTo((string)data.First().City);
43+
}
44+
45+
[Fact]
46+
public void Test_ContainsKey_2()
47+
{
48+
List<Customer> customers = new List<Customer>()
49+
{
50+
new Customer() { City = "ZZZ1", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() },
51+
new Customer() { City = "ZZZ2", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() },
52+
new Customer() { City = "ZZZ3", CompanyName = "ZZZ", Orders = new Dictionary<string, Order>() }
53+
};
54+
customers.ForEach(x => x.Orders.Add(x.City + "TEST", new Order()));
55+
56+
57+
58+
var data = customers.AsQueryable()
59+
.Where("Orders.ContainsKey(it.City + \"TEST\")")
60+
.OrderBy("City")
61+
.Select("new(City as City, Phone)").ToDynamicList();
62+
63+
Check.That("ZZZ1").IsEqualTo((string)data.First().City);
64+
Check.That(3).IsEqualTo(data.Count);
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)