1
+
using Signum.Entities.Reflection;
2
+
using Signum.Utilities.Reflection;
3
+
using System.ComponentModel;
4
+
5
+
namespace Signum.Entities.DynamicQuery;
6
+
7
+
public class CollectionToArrayToken : QueryToken
8
+
{
9
+
public CollectionToArrayType ToArrayType { get; private set; }
10
+
11
+
QueryToken parent;
12
+
public override QueryToken? Parent => parent;
13
+
14
+
readonly Type elementType;
15
+
internal CollectionToArrayToken(QueryToken parent, CollectionToArrayType toArrayType)
16
+
{
17
+
elementType = parent.Type.ElementType()!;
18
+
if (elementType == null)
19
+
throw new InvalidOperationException("not a collection");
20
+
21
+
this.ToArrayType = toArrayType;
22
+
23
+
this.parent = parent ?? throw new ArgumentNullException(nameof(parent));
24
+
}
25
+
26
+
public override Type Type
27
+
{
28
+
get { return elementType.BuildLiteNullifyUnwrapPrimaryKey(new[] { this.GetPropertyRoute()! }); }
29
+
}
30
+
31
+
public override string ToString()
32
+
{
33
+
return ToArrayType.NiceToString();
34
+
}
35
+
36
+
public override string Key
37
+
{
38
+
get { return ToArrayType.ToString(); }
39
+
}
40
+
41
+
protected override List<QueryToken> SubTokensOverride(SubTokensOptions options)
42
+
{
43
+
var st = SubTokensBase(Type, options, GetImplementations());
44
+
45
+
var ept = MListElementPropertyToken.AsMListEntityProperty(this.parent);
46
+
if (ept != null)
47
+
{
48
+
var mleType = MListElementPropertyToken.MListElementType(ept);
49
+
50
+
st.Add(new MListElementPropertyToken(this, mleType.GetProperty("RowId")!, ept.PropertyRoute, "RowId", () => QueryTokenMessage.RowId.NiceToString()) { Priority = -5 });
51
+
52
+
if (MListElementPropertyToken.HasAttribute(ept.PropertyRoute, typeof(PreserveOrderAttribute)))
53
+
st.Add(new MListElementPropertyToken(this, mleType.GetProperty("RowOrder")!, ept.PropertyRoute, "RowOrder", () => QueryTokenMessage.RowOrder.NiceToString()) { Priority = -5 });
54
+
}
55
+
56
+
return st;
57
+
}
58
+
59
+
public override Implementations? GetImplementations()
60
+
{
61
+
return parent.GetElementImplementations();
62
+
}
63
+
64
+
public override string? Format
65
+
{
66
+
get
67
+
{
68
+
69
+
if (Parent is ExtensionToken et && et.IsProjection)
70
+
return et.ElementFormat;
71
+
72
+
return parent.Format;
73
+
}
74
+
}
75
+
76
+
public override string? Unit
77
+
{
78
+
get
79
+
{
80
+
81
+
if (Parent is ExtensionToken et && et.IsProjection)
82
+
return et.ElementUnit;
83
+
84
+
return parent.Unit;
85
+
}
86
+
}
87
+
88
+
public override string? IsAllowed()
89
+
{
90
+
return parent.IsAllowed();
91
+
}
92
+
93
+
94
+
public override CollectionToArrayToken? HasToArray() => this;
95
+
96
+
public override PropertyRoute? GetPropertyRoute()
97
+
{
98
+
if (parent is ExtensionToken et && et.IsProjection)
99
+
return et.GetElementPropertyRoute();
100
+
101
+
PropertyRoute? pr = this.parent!.GetPropertyRoute();
102
+
if (pr != null && pr.Type.ElementType() != null)
103
+
return pr.Add("Item");
104
+
105
+
return pr;
106
+
}
107
+
108
+
public override string NiceName()
109
+
{
110
+
return this.parent.NiceName();
111
+
}
112
+
113
+
public override QueryToken Clone()
114
+
{
115
+
return new CollectionToArrayToken(parent.Clone(), ToArrayType);
116
+
}
117
+
118
+
protected override Expression BuildExpressionInternal(BuildExpressionContext context)
119
+
{
120
+
throw new InvalidOperationException("ToArrayToken should have a replacement at this stage");
121
+
}
122
+
123
+
124
+
public override string TypeColor
125
+
{
126
+
get { return "#0000FF"; }
127
+
}
128
+
129
+
public static int MaxToArrayValues = 100;
130
+
131
+
static MethodInfo miToArray = ReflectionTools.GetMethodInfo(() => Enumerable.ToArray<int>(null!)).GetGenericMethodDefinition();
132
+
static MethodInfo miToDistict = ReflectionTools.GetMethodInfo(() => Enumerable.Distinct<int>(null!)).GetGenericMethodDefinition();
133
+
static MethodInfo miSelect = ReflectionTools.GetMethodInfo(() => Enumerable.Select<int, long>(null!, a => a)).GetGenericMethodDefinition();
134
+
static MethodInfo miTake = ReflectionTools.GetMethodInfo(() => Enumerable.Take<int>(null!, 0)).GetGenericMethodDefinition();
135
+
static MethodInfo miSelectMany = ReflectionTools.GetMethodInfo(() => Enumerable.SelectMany<string, char>(null!, a => a)).GetGenericMethodDefinition();
136
+
137
+
internal static Expression BuildToArrayExpression(QueryToken token, CollectionToArrayToken cta, BuildExpressionContext context)
138
+
{
139
+
var ept = MListElementPropertyToken.AsMListEntityProperty(cta.Parent!);
140
+
141
+
BuildExpressionContext subCtx;
142
+
Expression query;
143
+
if(ept != null)
144
+
{
145
+
var collection = MListElementPropertyToken.BuildMListElements(ept, context);
146
+
query = collection;
147
+
Type mleType = collection.Type.ElementType()!;
148
+
var param = Expression.Parameter(mleType, mleType.Name.Substring(0, 1).ToLower());
149
+
subCtx = new BuildExpressionContext(mleType, param, new Dictionary<QueryToken, ExpressionBox>
150
+
{
151
+
{ cta, new ExpressionBox(param, mlistElementRoute: cta.GetPropertyRoute()) }
152
+
});
153
+
}
154
+
else
155
+
{
156
+
var collection = cta.Parent!.BuildExpression(context);
157
+
query = collection;
158
+
Type elemeType = collection.Type.ElementType()!;
159
+
var param = Expression.Parameter(elemeType, elemeType.Name.Substring(0, 1).ToLower());
160
+
subCtx = new BuildExpressionContext(elemeType, param, new Dictionary<QueryToken, ExpressionBox>()
161
+
{
162
+
{ cta, new ExpressionBox(param.BuildLiteNullifyUnwrapPrimaryKey(new[] { cta.GetPropertyRoute()! }))}
163
+
});
164
+
}
165
+
166
+
Expression body;
167
+
if (token is CollectionToArrayToken)
168
+
{
169
+
body = subCtx.Parameter.BuildLite();
170
+
}
171
+
else
172
+
{
173
+
var cets = token.Follow(a => a.Parent).TakeWhile(a => a != cta).OfType<CollectionElementToken>().Reverse().ToList();
174
+
foreach (var ce in cets)
175
+
{
176
+
var ept2 = MListElementPropertyToken.AsMListEntityProperty(ce.Parent!);
177
+
if (ept2 != null)
178
+
{
179
+
var collection = MListElementPropertyToken.BuildMListElements(ept2, subCtx);
180
+
Type mleType = collection.Type.ElementType()!;
181
+
query = Expression.Call(miSelectMany.MakeGenericMethod(query.Type.ElementType()!, mleType), query, Expression.Lambda(collection, subCtx.Parameter));
182
+
var param = Expression.Parameter(mleType, mleType.Name.Substring(0, 1).ToLower());
183
+
subCtx = new BuildExpressionContext(mleType, param, new Dictionary<QueryToken, ExpressionBox>()
184
+
{
185
+
{ ce, new ExpressionBox(param, mlistElementRoute: ce.GetPropertyRoute())}
186
+
});
187
+
}
188
+
else
189
+
{
190
+
var collection = ce.Parent!.BuildExpression(subCtx);
191
+
Type elementType = collection.Type.ElementType()!;
192
+
query = Expression.Call(miSelectMany.MakeGenericMethod(query.Type.ElementType()!, elementType), query, Expression.Lambda(collection, subCtx.Parameter));
193
+
194
+
var param = Expression.Parameter(elementType, elementType.Name.Substring(0, 1).ToLower());
195
+
subCtx = new BuildExpressionContext(elementType, param, new Dictionary<QueryToken, ExpressionBox>()
196
+
{
197
+
{ ce, new ExpressionBox(param.BuildLiteNullifyUnwrapPrimaryKey(new[] { ce.GetPropertyRoute()! }))}
198
+
});
199
+
}
200
+
}
201
+
202
+
body = token.BuildExpression(subCtx);
203
+
}
204
+
205
+
if (body != subCtx.Parameter)
206
+
query = Expression.Call(miSelect.MakeGenericMethod(query.Type.ElementType()!, body.Type), query, Expression.Lambda(body, subCtx.Parameter));
207
+
208
+
if (cta.ToArrayType == CollectionToArrayType.SeparatedByCommaDistict ||
209
+
cta.ToArrayType == CollectionToArrayType.SeparatedByNewLineDistict)
210
+
query = Expression.Call(miToDistict.MakeGenericMethod(token.Type), query);
211
+
212
+
query = Expression.Call(miTake.MakeGenericMethod(token.Type), query, Expression.Constant(MaxToArrayValues));
213
+
214
+
return Expression.Call(miToArray.MakeGenericMethod(token.Type), query);
215
+
}
216
+
}
217
+
218
+
[DescriptionOptions(DescriptionOptions.Members)]
219
+
public enum CollectionToArrayType
220
+
{
221
+
SeparatedByComma,
222
+
SeparatedByCommaDistict,
223
+
SeparatedByNewLine,
224
+
SeparatedByNewLineDistict,
225
+
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4