annotate Source/Data/Linq/Builder/ExpressionBuilder.cs @ 9:1e85f66cf767 default tip

update bltoolkit
author nickolay
date Thu, 05 Apr 2018 20:53:26 +0300
parents 11b6da379593
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Data;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 using Common;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 using Data.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 using Data.Sql.SqlProvider;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 using Mapping;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 using Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 public partial class ExpressionBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 #region Sequence
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 static readonly object _sync = new object();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 static List<ISequenceBuilder> _sequenceBuilders = new List<ISequenceBuilder>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 new TableBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 new SelectBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28 new SelectManyBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 new WhereBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 new OrderByBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 new GroupByBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 new JoinBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 new TakeSkipBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 new DefaultIfEmptyBuilder(),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 new DistinctBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 new FirstSingleBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 new AggregationBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 new ScalarSelectBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 new CountBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 new PassThroughBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 new TableAttributeBuilder(),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 new InsertBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 new InsertBuilder.Into (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 new InsertBuilder.Value (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 new InsertOrUpdateBuilder(),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 new UpdateBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 new UpdateBuilder.Set (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 new DeleteBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 new ContainsBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 new AllAnyBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 new ConcatUnionBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 new IntersectBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 new CastBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 new OfTypeBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 new AsUpdatableBuilder (),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 public static void AddBuilder(ISequenceBuilder builder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 _sequenceBuilders.Add(builder);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 #region Init
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 readonly Query _query;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 readonly List<ISequenceBuilder> _builders = _sequenceBuilders;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 private bool _reorder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 readonly Dictionary<Expression,Expression> _expressionAccessors;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 private HashSet<Expression> _subQueryExpressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 readonly public List<ParameterAccessor> CurrentSqlParameters = new List<ParameterAccessor>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 #if FW4 || SILVERLIGHT
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 readonly public List<ParameterExpression> BlockVariables = new List<ParameterExpression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 readonly public List<Expression> BlockExpressions = new List<Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 public bool IsBlockDisable;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 #else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 public bool IsBlockDisable = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 #endif
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 readonly HashSet<Expression> _visitedExpressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 public ExpressionBuilder(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 Query query,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 IDataContextInfo dataContext,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 Expression expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 ParameterExpression[] compiledParameters)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 _query = query;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 _expressionAccessors = expression.GetExpressionAccessors(ExpressionParam);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 CompiledParameters = compiledParameters;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 DataContextInfo = dataContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 OriginalExpression = expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 _visitedExpressions = new HashSet<Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 Expression = ConvertExpressionTree(expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 _visitedExpressions = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 #region Public Members
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 public readonly IDataContextInfo DataContextInfo;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 public readonly Expression OriginalExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 public readonly Expression Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 public readonly ParameterExpression[] CompiledParameters;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 public readonly List<IBuildContext> Contexts = new List<IBuildContext>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 private ISqlProvider _sqlProvider;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 public ISqlProvider SqlProvider
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 get { return _sqlProvider ?? (_sqlProvider = DataContextInfo.CreateSqlProvider()); }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 public static readonly ParameterExpression ContextParam = Expression.Parameter(typeof(QueryContext), "context");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 public static readonly ParameterExpression DataContextParam = Expression.Parameter(typeof(IDataContext), "dctx");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 public static readonly ParameterExpression DataReaderParam = Expression.Parameter(typeof(IDataReader), "rd");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 public static readonly ParameterExpression ParametersParam = Expression.Parameter(typeof(object[]), "ps");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 public static readonly ParameterExpression ExpressionParam = Expression.Parameter(typeof(Expression), "expr");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 public MappingSchema MappingSchema
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 get { return DataContextInfo.MappingSchema; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 #region Builder SQL
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 internal Query<T> Build<T>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 var sequence = BuildSequence(new BuildInfo((IBuildContext)null, Expression, new SqlQuery()));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 if (_reorder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 lock (_sync)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 _reorder = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 _sequenceBuilders = _sequenceBuilders.OrderByDescending(_ => _.BuildCounter).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 _query.Init(sequence, CurrentSqlParameters);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 var param = Expression.Parameter(typeof(Query<T>), "info");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 sequence.BuildQuery((Query<T>)_query, param);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 return (Query<T>)_query;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 [JetBrains.Annotations.NotNull]
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 public IBuildContext BuildSequence(BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 buildInfo.Expression = buildInfo.Expression.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 var n = _builders[0].BuildCounter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 foreach (var builder in _builders)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 if (builder.CanBuild(this, buildInfo))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 var sequence = builder.BuildSequence(this, buildInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 lock (builder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 builder.BuildCounter++;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 _reorder = _reorder || n < builder.BuildCounter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 return sequence;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 n = builder.BuildCounter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 throw new LinqException("Sequence '{0}' cannot be converted to SQL.", buildInfo.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 public SequenceConvertInfo ConvertSequence(BuildInfo buildInfo, ParameterExpression param)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 buildInfo.Expression = buildInfo.Expression.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 foreach (var builder in _builders)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188 if (builder.CanBuild(this, buildInfo))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 return builder.Convert(this, buildInfo, param);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 throw new LinqException("Sequence '{0}' cannot be converted to SQL.", buildInfo.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194 public bool IsSequence(BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 buildInfo.Expression = buildInfo.Expression.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198 foreach (var builder in _builders)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 if (builder.CanBuild(this, buildInfo))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 return builder.IsSequence(this, buildInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 #region ConvertExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209 public ParameterExpression SequenceParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 Expression ConvertExpressionTree(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 var expr = ConvertParameters(expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 expr = ExposeExpression (expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 expr = OptimizeExpression(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218 var paramType = expr.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 var isQueryable = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221 if (expression.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 var call = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 if (call.IsQueryable() && call.Object == null && call.Arguments.Count > 0 && call.Type.IsGenericType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 var type = call.Type.GetGenericTypeDefinition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 if (type == typeof(IQueryable<>) || type == typeof(IEnumerable<>))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 var arg = call.Type.GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233 if (arg.Length == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235 paramType = arg[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 isQueryable = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242 SequenceParameter = Expression.Parameter(paramType, "cp");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 var sequence = ConvertSequence(new BuildInfo((IBuildContext)null, expr, new SqlQuery()), SequenceParameter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 if (sequence != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 if (sequence.Expression.Type != expr.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 if (isQueryable)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 var p = sequence.ExpressionsToReplace.SingleOrDefault(s => s.Path.NodeType == ExpressionType.Parameter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 return Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 ((MethodCallExpression)expr).Method.DeclaringType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 "Select",
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 new[] { p.Path.Type, paramType },
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258 sequence.Expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 Expression.Lambda(p.Expr, (ParameterExpression)p.Path));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 return sequence.Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271 #region ConvertParameters
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 Expression ConvertParameters(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 return expression.Convert(expr =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 switch (expr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279 case ExpressionType.Parameter:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 if (CompiledParameters != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 var idx = Array.IndexOf(CompiledParameters, (ParameterExpression)expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284 if (idx > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285 return
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 Expression.Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 Expression.ArrayIndex(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 ParametersParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 Expression.Constant(Array.IndexOf(CompiledParameters, (ParameterExpression)expr))),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 #region ExposeExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 Expression ExposeExpression(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 return expression.Convert(expr =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 switch (expr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 case ExpressionType.MemberAccess:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312 var me = (MemberExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313 var l = ConvertMethodExpression(me.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 if (l != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317 var body = l.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318 var ex = body.Convert2(wpi => new ExpressionHelper.ConvertInfo(wpi.NodeType == ExpressionType.Parameter ? me.Expression : wpi));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320 if (ex.Type != expr.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321 ex = new ChangeTypeExpression(ex, expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 return ExposeExpression(ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
324 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
325
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
326 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
327 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
328
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
329 case ExpressionType.Constant :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
330 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
331 var c = (ConstantExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
332
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
333 // Fix Mono behaviour.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
334 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
335 //if (c.Value is IExpressionQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
336 // return ((IQueryable)c.Value).Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
337
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
338 if (c.Value is IQueryable && !(c.Value is ITable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
339 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
340 var e = ((IQueryable)c.Value).Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
341
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
342 if (!_visitedExpressions.Contains(e))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
343 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
344 _visitedExpressions.Add(e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
345 return ExposeExpression(e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
346 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
347 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
348
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
349 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
350 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
351 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
352
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
353 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
354 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
355 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
356
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
357 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
358
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
359 #region OptimizeExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
360
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
361 private MethodInfo[] _enumerableMethods;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
362 public MethodInfo[] EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
363 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
364 get { return _enumerableMethods ?? (_enumerableMethods = typeof(Enumerable).GetMethods()); }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
365 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
366
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
367 private MethodInfo[] _queryableMethods;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
368 public MethodInfo[] QueryableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
369 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
370 get { return _queryableMethods ?? (_queryableMethods = typeof(Queryable).GetMethods()); }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
371 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
372
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
373 readonly Dictionary<Expression,Expression> _optimizedExpressions = new Dictionary<Expression,Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
374
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
375 Expression OptimizeExpression(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
376 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
377 Expression expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
378
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
379 if (_optimizedExpressions.TryGetValue(expression, out expr))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
380 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
381
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
382 _optimizedExpressions[expression] = expr = expression.Convert(OptimizeExpressionImpl);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
383
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
384 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
385 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
386
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
387 Expression OptimizeExpressionImpl(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
388 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
389 switch (expr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
390 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
391 case ExpressionType.MemberAccess:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
392 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
393 var me = (MemberExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
394
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
395 // Replace Count with Count()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
396 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
397 if (me.Member.Name == "Count")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
398 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
399 var isList = typeof(ICollection).IsAssignableFrom(me.Member.DeclaringType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
400
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
401 if (!isList)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
402 isList = me.Member.DeclaringType.GetInterfaces()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
403 .Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IList<>));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
404
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
405 if (isList)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
406 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
407 var mi = EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
408 .First(m => m.Name == "Count" && m.GetParameters().Length == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
409 .MakeGenericMethod(TypeHelper.GetElementType(me.Expression.Type));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
410
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
411 return Expression.Call(null, mi, me.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
412 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
413 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
414
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
415 if (CompiledParameters == null && TypeHelper.IsSameOrParent(typeof(IQueryable), expr.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
416 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
417 var ex = ConvertIQueriable(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
418
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
419 if (ex != expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
420 return ConvertExpressionTree(ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
421 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
422
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
423 return ConvertSubquery(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
424 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
425
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
426 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
427 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
428 var call = (MethodCallExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
429
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
430 if (call.IsQueryable())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
431 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
432 switch (call.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
433 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
434 case "Where" : return ConvertWhere (call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
435 case "GroupBy" : return ConvertGroupBy (call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
436 case "SelectMany" : return ConvertSelectMany(call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
437 case "Select" : return ConvertSelect (call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
438 case "LongCount" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
439 case "Count" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
440 case "Single" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
441 case "SingleOrDefault" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
442 case "First" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
443 case "FirstOrDefault" : return ConvertPredicate (call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
444 case "Min" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
445 case "Max" : return ConvertSelector (call, true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
446 case "Sum" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
447 case "Average" : return ConvertSelector (call, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
448 case "ElementAt" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
449 case "ElementAtOrDefault" : return ConvertElementAt (call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
450 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
451 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
452 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
453 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
454 var l = ConvertMethodExpression(call.Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
455
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
456 if (l != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
457 return OptimizeExpression(ConvertMethod(call, l));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
458
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
459 if (CompiledParameters == null && TypeHelper.IsSameOrParent(typeof(IQueryable), expr.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
460 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
461 var attr = GetTableFunctionAttribute(call.Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
462
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
463 if (attr == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
464 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
465 var ex = ConvertIQueriable(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
466
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
467 if (ex != expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
468 return ConvertExpressionTree(ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
469 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
470 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
471 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
472
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
473 return ConvertSubquery(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
474 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
475 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
476
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
477 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
478 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
479
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
480 LambdaExpression ConvertMethodExpression(MemberInfo mi)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
481 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
482 var attrs = mi.GetCustomAttributes(typeof(MethodExpressionAttribute), true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
483
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
484 if (attrs.Length == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
485 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
486
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
487 MethodExpressionAttribute attr = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
488
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
489 foreach (MethodExpressionAttribute a in attrs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
490 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
491 if (a.SqlProvider == SqlProvider.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
492 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
493 attr = a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
494 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
495 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
496
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
497 if (a.SqlProvider == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
498 attr = a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
499 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
500
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
501 if (attr != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
502 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
503 Expression expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
504
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
505 if (mi is MethodInfo && ((MethodInfo)mi).IsGenericMethod)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
506 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
507 var method = (MethodInfo)mi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
508 var args = method.GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
509 var names = args.Select(t => t.Name).ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
510 var name = string.Format(attr.MethodName, names);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
511
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
512 if (name != attr.MethodName)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
513 expr = Expression.Call(mi.DeclaringType, name, Array<Type>.Empty);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
514 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
515 expr = Expression.Call(mi.DeclaringType, name, args);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
516 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
517 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
518 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
519 expr = Expression.Call(mi.DeclaringType, attr.MethodName, Array<Type>.Empty);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
520 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
521
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
522 var call = Expression.Lambda<Func<LambdaExpression>>(Expression.Convert(expr, typeof(LambdaExpression)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
523
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
524 return call.Compile()();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
525 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
526
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
527 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
528 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
529
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
530 Expression ConvertSubquery(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
531 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
532 var ex = expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
533
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
534 while (ex != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
535 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
536 switch (ex.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
537 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
538 default : return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
539 case ExpressionType.MemberAccess : ex = ((MemberExpression)ex).Expression; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
540 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
541 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
542 var call = (MethodCallExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
543
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
544 if (call.Object == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
545 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
546 if (call.IsQueryable()) switch (call.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
547 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
548 case "Single" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
549 case "SingleOrDefault" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
550 case "First" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
551 case "FirstOrDefault" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
552 return ConvertSingleOrFirst(expr, call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
553 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
554
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
555 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
556 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
557
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
558 ex = call.Object;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
559
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
560 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
561 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
562 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
563 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
564
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
565 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
566 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
567
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
568 Expression ConvertSingleOrFirst(Expression expr, MethodCallExpression call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
569 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
570 var param = Expression.Parameter(call.Type, "p");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
571 var selector = expr.Convert(e => e == call ? param : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
572 var method = GetQueriableMethodInfo(call, (m, _) => m.Name == call.Method.Name && m.GetParameters().Length == 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
573 var select = call.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
574 EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
575 .Where(m => m.Name == "Select" && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
576 .First(m => m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
577 QueryableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
578 .Where(m => m.Name == "Select" && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
579 .First(m => m.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
580
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
581 call = (MethodCallExpression)OptimizeExpression(call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
582 select = select.MakeGenericMethod(call.Type, expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
583 method = method.MakeGenericMethod(expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
584
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
585 return Expression.Call(null, method,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
586 Expression.Call(null, select,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
587 call.Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
588 Expression.Lambda(selector, param)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
589 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
590
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
591 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
592
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
593 #region ConvertWhere
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
594
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
595 Expression ConvertWhere(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
596 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
597 var sequence = OptimizeExpression(method.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
598 var predicate = OptimizeExpression(method.Arguments[1]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
599 var lambda = (LambdaExpression)predicate.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
600 var lparam = lambda.Parameters[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
601 var lbody = lambda.Body;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
602
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
603 if (lambda.Parameters.Count > 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
604 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
605
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
606 var exprs = new List<Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
607
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
608 lbody.Visit(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
609 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
610 if (ex.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
611 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
612 var call = (MethodCallExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
613
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
614 if (call.Arguments.Count > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
615 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
616 var arg = call.Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
617
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
618 if (call.IsQueryable(AggregationBuilder.MethodNames))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
619 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
620 while (arg.NodeType == ExpressionType.Call && ((MethodCallExpression) arg).Method.Name == "Select")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
621 arg = ((MethodCallExpression) arg).Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
622
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
623 if (arg.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
624 exprs.Add(ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
625 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
626 else if (call.IsQueryable(CountBuilder.MethodNames))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
627 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
628 //while (arg.NodeType == ExpressionType.Call && ((MethodCallExpression) arg).Method.Name == "Select")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
629 // arg = ((MethodCallExpression) arg).Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
630
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
631 if (arg.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
632 exprs.Add(ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
633 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
634 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
635 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
636 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
637
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
638 Expression expr = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
639
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
640 if (exprs.Count > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
641 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
642 expr = lparam;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
643
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
644 foreach (var ex in exprs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
645 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
646 var type = typeof(ExpressionHoder<,>).MakeGenericType(expr.Type, ex.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
647 var fields = type.GetFields();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
648
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
649 expr = Expression.MemberInit(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
650 Expression.New(type),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
651 Expression.Bind(fields[0], expr),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
652 Expression.Bind(fields[1], ex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
653 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
654
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
655 var dic = new Dictionary<Expression, Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
656 var parm = Expression.Parameter(expr.Type, lparam.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
657
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
658 for (var i = 0; i < exprs.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
659 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
660 Expression ex = parm;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
661
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
662 for (var j = i; j < exprs.Count - 1; j++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
663 ex = Expression.PropertyOrField(ex, "p");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
664
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
665 ex = Expression.PropertyOrField(ex, "ex");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
666
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
667 dic.Add(exprs[i], ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
668
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
669 if (_subQueryExpressions == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
670 _subQueryExpressions = new HashSet<Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
671 _subQueryExpressions.Add(ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
672 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
673
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
674 var newBody = lbody.Convert(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
675 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
676 Expression e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
677 return dic.TryGetValue(ex, out e) ? e : ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
678 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
679
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
680 var nparm = exprs.Aggregate<Expression,Expression>(parm, (c,t) => Expression.PropertyOrField(c, "p"));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
681
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
682 newBody = newBody.Convert(ex => ex == lparam ? nparm : ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
683
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
684 predicate = Expression.Lambda(newBody, parm);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
685
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
686 var methodInfo = GetMethodInfo(method, "Select");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
687
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
688 methodInfo = methodInfo.MakeGenericMethod(lparam.Type, expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
689 sequence = Expression.Call(methodInfo, sequence, Expression.Lambda(expr, lparam));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
690 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
691
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
692 if (sequence != method.Arguments[0] || predicate != method.Arguments[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
693 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
694 var methodInfo = method.Method.GetGenericMethodDefinition();
6
11b6da379593 Исправлена странная ошибка при использовании OfType<...>().Where(...)
cin
parents: 5
diff changeset
695 var queryableType = sequence.Type.GetInterface(typeof(IEnumerable<>).Name);
5
f7d63a092920 Исправлено условие Where в тех случаях, когда репозитарий не является генериком
cin
parents: 0
diff changeset
696 var genericType = queryableType.GetGenericArguments()[0];
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
697 var newMethod = methodInfo.MakeGenericMethod(genericType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
698
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
699 method = Expression.Call(newMethod, sequence, predicate);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
700
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
701 if (exprs.Count > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
702 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
703 var parameter = Expression.Parameter(expr.Type, lparam.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
704
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
705 methodInfo = GetMethodInfo(method, "Select");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
706 methodInfo = methodInfo.MakeGenericMethod(expr.Type, lparam.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
707 method = Expression.Call(methodInfo, method,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
708 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
709 exprs.Aggregate((Expression)parameter, (current,_) => Expression.PropertyOrField(current, "p")),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
710 parameter));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
711 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
712 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
713
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
714 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
715 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
716
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
717 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
718
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
719 #region ConvertGroupBy
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
720
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
721 public class GroupSubQuery<TKey,TElement>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
722 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
723 public TKey Key;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
724 public TElement Element;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
725 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
726
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
727 interface IGroupByHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
728 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
729 void Set(bool wrapInSubQuery, Expression sourceExpression, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
730
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
731 Expression AddElementSelectorQ ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
732 Expression AddElementSelectorE ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
733 Expression AddResultQ ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
734 Expression AddResultE ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
735 Expression WrapInSubQueryQ ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
736 Expression WrapInSubQueryE ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
737 Expression WrapInSubQueryResultQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
738 Expression WrapInSubQueryResultE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
739 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
740
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
741 class GroupByHelper<TSource,TKey,TElement,TResult> : IGroupByHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
742 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
743 bool _wrapInSubQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
744 Expression _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
745 LambdaExpression _keySelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
746 LambdaExpression _elementSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
747 LambdaExpression _resultSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
748
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
749 public void Set(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
750 bool wrapInSubQuery,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
751 Expression sourceExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
752 LambdaExpression keySelector,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
753 LambdaExpression elementSelector,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
754 LambdaExpression resultSelector)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
755 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
756 _wrapInSubQuery = wrapInSubQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
757 _sourceExpression = sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
758 _keySelector = keySelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
759 _elementSelector = elementSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
760 _resultSelector = resultSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
761 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
762
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
763 public Expression AddElementSelectorQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
764 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
765 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<IGrouping<TKey,TSource>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
766 .GroupBy(keyParam => key, _ => _)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
767 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
768
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
769 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
770 var keyArg = GetLambda(body, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
771
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
772 return Convert(func, keyArg, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
773 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
774
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
775 public Expression AddElementSelectorE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
776 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
777 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<IGrouping<TKey,TSource>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
778 .GroupBy(keyParam => key, _ => _)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
779 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
780
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
781 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
782 var keyArg = GetLambda(body, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
783
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
784 return Convert(func, keyArg, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
785 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
786
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
787 public Expression AddResultQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
788 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
789 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
790 .GroupBy(keyParam => key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
791 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
792 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
793
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
794 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
795 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
796 var elemArg = GetLambda(body, 0, 2).Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
797 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
798
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
799 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
800 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
801
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
802 public Expression AddResultE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
803 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
804 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
805 .GroupBy(keyParam => key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
806 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
807 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
808
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
809 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
810 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
811 var elemArg = GetLambda(body, 0, 2).Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
812 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
813
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
814 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
815 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
816
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
817 public Expression WrapInSubQueryQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
818 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
819 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<IGrouping<TKey,TElement>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
820 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
821 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
822 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
823 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
824 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
825 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
826 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
827
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
828 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
829 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
830 var elemArg = GetLambda(body, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
831
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
832 return Convert(func, keyArg, elemArg, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
833 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
834
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
835 public Expression WrapInSubQueryE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
836 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
837 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<IGrouping<TKey,TElement>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
838 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
839 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
840 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
841 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
842 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
843 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
844 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
845
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
846 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
847 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
848 var elemArg = GetLambda(body, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
849
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
850 return Convert(func, keyArg, elemArg, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
851 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
852
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
853 public Expression WrapInSubQueryResultQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
854 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
855 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
856 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
857 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
858 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
859 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
860 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
861 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
862 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
863 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
864
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
865 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
866 var keyArg = GetLambda(body, 0, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
867 var elemArg = GetLambda(body, 0, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
868 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
869
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
870 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
871 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
872
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
873 public Expression WrapInSubQueryResultE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
874 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
875 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
876 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
877 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
878 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
879 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
880 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
881 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
882 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
883 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
884
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
885 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
886 var keyArg = GetLambda(body, 0, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
887 var elemArg = GetLambda(body, 0, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
888 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
889
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
890 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
891 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
892
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
893 Expression Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
894 LambdaExpression func,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
895 ParameterExpression keyArg,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
896 ParameterExpression elemArg,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
897 ParameterExpression resArg)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
898 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
899 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
900 var expr = body.Convert(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
901 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
902 if (ex == func.Parameters[0])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
903 return _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
904
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
905 if (ex == func.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
906 return _keySelector.Body.Convert(e => e == _keySelector.Parameters[0] ? keyArg : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
907
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
908 if (ex == func.Parameters[2])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
909 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
910 Expression obj = elemArg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
911
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
912 if (_wrapInSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
913 obj = Expression.PropertyOrField(elemArg, "Element");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
914
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
915 if (_elementSelector == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
916 return obj;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
917
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
918 return _elementSelector.Body.Convert(e => e == _elementSelector.Parameters[0] ? obj : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
919 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
920
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
921 if (ex == func.Parameters[3])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
922 return _resultSelector.Body.Convert(e =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
923 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
924 if (e == _resultSelector.Parameters[0])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
925 return Expression.PropertyOrField(resArg, "Key");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
926
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
927 if (e == _resultSelector.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
928 return resArg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
929
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
930 return e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
931 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
932
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
933 return ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
934 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
935
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
936 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
937 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
938 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
939
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
940 static LambdaExpression GetLambda(Expression expression, params int[] n)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
941 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
942 foreach (var i in n)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
943 expression = ((MethodCallExpression)expression).Arguments[i].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
944 return (LambdaExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
945 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
946
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
947 Expression ConvertGroupBy(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
948 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
949 if (method.Arguments[method.Arguments.Count - 1].Unwrap().NodeType != ExpressionType.Lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
950 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
951
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
952 var types = method.Method.GetGenericMethodDefinition().GetGenericArguments()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
953 .Zip(method.Method.GetGenericArguments(), (n, t) => new { n = n.Name, t })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
954 .ToDictionary(_ => _.n, _ => _.t);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
955
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
956 var sourceExpression = OptimizeExpression(method.Arguments[0].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
957 var keySelector = (LambdaExpression)OptimizeExpression(method.Arguments[1].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
958 var elementSelector = types.ContainsKey("TElement") ? (LambdaExpression)OptimizeExpression(method.Arguments[2].Unwrap()) : null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
959 var resultSelector = types.ContainsKey("TResult") ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
960 (LambdaExpression)OptimizeExpression(method.Arguments[types.ContainsKey("TElement") ? 3 : 2].Unwrap()) : null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
961
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
962 var needSubQuery = null != ConvertExpression(keySelector.Body.Unwrap()).Find(IsExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
963
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
964 if (!needSubQuery && resultSelector == null && elementSelector != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
965 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
966
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
967 var gtype = typeof(GroupByHelper<,,,>).MakeGenericType(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
968 types["TSource"],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
969 types["TKey"],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
970 types.ContainsKey("TElement") ? types["TElement"] : types["TSource"],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
971 types.ContainsKey("TResult") ? types["TResult"] : types["TSource"]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
972
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
973 var helper =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
974 //Expression.Lambda<Func<IGroupByHelper>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
975 // Expression.Convert(Expression.New(gtype), typeof(IGroupByHelper)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
976 //.Compile()();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
977 (IGroupByHelper)Activator.CreateInstance(gtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
978
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
979 helper.Set(needSubQuery, sourceExpression, keySelector, elementSelector, resultSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
980
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
981 if (method.Method.DeclaringType == typeof(Queryable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
982 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
983 if (!needSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
984 return resultSelector == null ? helper.AddElementSelectorQ() : helper.AddResultQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
985
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
986 return resultSelector == null ? helper.WrapInSubQueryQ() : helper.WrapInSubQueryResultQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
987 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
988 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
989 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
990 if (!needSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
991 return resultSelector == null ? helper.AddElementSelectorE() : helper.AddResultE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
992
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
993 return resultSelector == null ? helper.WrapInSubQueryE() : helper.WrapInSubQueryResultE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
994 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
995 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
996
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
997 bool IsExpression(Expression ex)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
998 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
999 switch (ex.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1000 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1001 case ExpressionType.Convert :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1002 case ExpressionType.ConvertChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1003 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1004 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1005 case ExpressionType.NewArrayBounds :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1006 case ExpressionType.NewArrayInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1007 case ExpressionType.Parameter : return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1008 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1009 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1010 var ma = (MemberExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1011 var attr = GetFunctionAttribute(ma.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1012
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1013 if (attr != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1014 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1015
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1016 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1017 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1018 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1019
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1020 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1021 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1022
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1023 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1024
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1025 #region ConvertSelectMany
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1026
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1027 interface ISelectManyHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1028 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1029 void Set(Expression sourceExpression, LambdaExpression colSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1030
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1031 Expression AddElementSelectorQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1032 Expression AddElementSelectorE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1033 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1034
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1035 class SelectManyHelper<TSource,TCollection> : ISelectManyHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1036 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1037 Expression _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1038 LambdaExpression _colSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1039
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1040 public void Set(Expression sourceExpression, LambdaExpression colSelector)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1041 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1042 _sourceExpression = sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1043 _colSelector = colSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1044 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1045
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1046 public Expression AddElementSelectorQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1047 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1048 Expression<Func<IQueryable<TSource>,IEnumerable<TCollection>,IQueryable<TCollection>>> func = (source,col) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1049 .SelectMany(colParam => col, (s,c) => c)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1050 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1051
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1052 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1053 var colArg = GetLambda(body, 1).Parameters[0]; // .SelectMany(colParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1054
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1055 return Convert(func, colArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1056 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1057
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1058 public Expression AddElementSelectorE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1059 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1060 Expression<Func<IEnumerable<TSource>,IEnumerable<TCollection>,IEnumerable<TCollection>>> func = (source,col) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1061 .SelectMany(colParam => col, (s,c) => c)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1062 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1063
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1064 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1065 var colArg = GetLambda(body, 1).Parameters[0]; // .SelectMany(colParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1066
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1067 return Convert(func, colArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1068 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1069
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1070 Expression Convert(LambdaExpression func, ParameterExpression colArg)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1071 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1072 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1073 var expr = body.Convert(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1074 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1075 if (ex == func.Parameters[0])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1076 return _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1077
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1078 if (ex == func.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1079 return _colSelector.Body.Convert(e => e == _colSelector.Parameters[0] ? colArg : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1080
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1081 return ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1082 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1083
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1084 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1085 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1086 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1087
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1088 Expression ConvertSelectMany(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1089 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1090 if (method.Arguments.Count != 2 || ((LambdaExpression)method.Arguments[1].Unwrap()).Parameters.Count != 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1091 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1092
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1093 var types = method.Method.GetGenericMethodDefinition().GetGenericArguments()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1094 .Zip(method.Method.GetGenericArguments(), (n, t) => new { n = n.Name, t })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1095 .ToDictionary(_ => _.n, _ => _.t);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1096
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1097 var sourceExpression = OptimizeExpression(method.Arguments[0].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1098 var colSelector = (LambdaExpression)OptimizeExpression(method.Arguments[1].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1099
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1100 var gtype = typeof(SelectManyHelper<,>).MakeGenericType(types["TSource"], types["TResult"]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1101 var helper =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1102 //Expression.Lambda<Func<ISelectManyHelper>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1103 // Expression.Convert(Expression.New(gtype), typeof(ISelectManyHelper)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1104 //.Compile()();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1105 (ISelectManyHelper)Activator.CreateInstance(gtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1106
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1107 helper.Set(sourceExpression, colSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1108
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1109 return method.Method.DeclaringType == typeof(Queryable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1110 helper.AddElementSelectorQ() :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1111 helper.AddElementSelectorE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1112 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1113
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1114 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1115
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1116 #region ConvertPredicate
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1117
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1118 Expression ConvertPredicate(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1119 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1120 if (method.Arguments.Count != 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1121 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1122
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1123 var cm = GetQueriableMethodInfo(method, (m,_) => m.Name == method.Method.Name && m.GetParameters().Length == 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1124 var wm = GetMethodInfo(method, "Where");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1125
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1126 var argType = method.Method.GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1127
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1128 wm = wm.MakeGenericMethod(argType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1129 cm = cm.MakeGenericMethod(argType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1130
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1131 return Expression.Call(null, cm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1132 Expression.Call(null, wm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1133 OptimizeExpression(method.Arguments[0]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1134 OptimizeExpression(method.Arguments[1])));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1135 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1136
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1137 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1138
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1139 #region ConvertSelector
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1140
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1141 Expression ConvertSelector(MethodCallExpression method, bool isGeneric)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1142 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1143 if (method.Arguments.Count != 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1144 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1145
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1146 isGeneric = isGeneric && method.Method.DeclaringType == typeof(Queryable);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1147
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1148 var types = GetMethodGenericTypes(method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1149 var sm = GetMethodInfo(method, "Select");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1150 var cm = GetQueriableMethodInfo(method, (m,isDefault) =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1151 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1152 if (m.Name == method.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1153 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1154 var ps = m.GetParameters();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1155
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1156 if (ps.Length == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1157 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1158 if (isGeneric)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1159 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1160
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1161 var ts = ps[0].ParameterType.GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1162 return ts[0] == types[1] || isDefault && ts[0].IsGenericParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1163 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1164 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1165
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1166 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1167 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1168
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1169 var argType = types[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1170
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1171 sm = sm.MakeGenericMethod(argType, types[1]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1172
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1173 if (cm.IsGenericMethodDefinition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1174 cm = cm.MakeGenericMethod(types[1]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1175
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1176 return Expression.Call(null, cm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1177 OptimizeExpression(Expression.Call(null, sm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1178 method.Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1179 method.Arguments[1])));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1180 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1181
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1182 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1183
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1184 #region ConvertSelect
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1185
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1186 Expression ConvertSelect(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1187 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1188 var sequence = OptimizeExpression(method.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1189 var lambda1 = (LambdaExpression)method.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1190 var lambda = (LambdaExpression)OptimizeExpression(lambda1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1191
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1192 if (lambda1.Parameters.Count > 1 ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1193 sequence.NodeType != ExpressionType.Call ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1194 ((MethodCallExpression)sequence).Method.Name != method.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1195 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1196 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1197 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1198
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1199 var slambda = (LambdaExpression)((MethodCallExpression)sequence).Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1200 var sbody = slambda.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1201
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1202 if (slambda.Parameters.Count > 1 || sbody.NodeType != ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1203 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1204
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1205 var types1 = GetMethodGenericTypes((MethodCallExpression)sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1206 var types2 = GetMethodGenericTypes(method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1207
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1208 var expr = Expression.Call(null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1209 GetMethodInfo(method, "Select").MakeGenericMethod(types1[0], types2[1]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1210 ((MethodCallExpression)sequence).Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1211 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1212 lambda.Body.Convert(ex => ex == lambda.Parameters[0] ? sbody : ex),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1213 slambda.Parameters[0]));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1214
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1215 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1216 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1217
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1218 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1219
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1220 #region ConvertIQueriable
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1221
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1222 Expression ConvertIQueriable(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1223 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1224 if (expression.NodeType == ExpressionType.MemberAccess || expression.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1225 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1226 var p = Expression.Parameter(typeof(Expression), "exp");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1227 var exas = expression.GetExpressionAccessors(p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1228 var expr = ReplaceParameter(exas, expression, _ => {});
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1229
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1230 if (expr.Find(e => e.NodeType == ExpressionType.Parameter && e != p) != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1231 return expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1232
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1233 var l = Expression.Lambda<Func<Expression,IQueryable>>(Expression.Convert(expr, typeof(IQueryable)), new [] { p });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1234 var n = _query.AddQueryableAccessors(expression, l);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1235
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1236 Expression accessor;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1237
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1238 _expressionAccessors.TryGetValue(expression, out accessor);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1239
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1240 var path =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1241 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1242 Expression.Constant(_query),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1243 ReflectionHelper.Expressor<Query>.MethodExpressor(a => a.GetIQueryable(0, null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1244 new[] { Expression.Constant(n), accessor ?? Expression.Constant(null, typeof(Expression)) });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1245
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1246 var qex = _query.GetIQueryable(n, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1247
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1248 if (expression.NodeType == ExpressionType.Call && qex.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1249 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1250 var m1 = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1251 var m2 = (MethodCallExpression)qex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1252
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1253 if (m1.Method == m2.Method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1254 return expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1255 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1256
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1257 foreach (var a in qex.GetExpressionAccessors(path))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1258 if (!_expressionAccessors.ContainsKey(a.Key))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1259 _expressionAccessors.Add(a.Key, a.Value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1260
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1261 return qex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1262 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1263
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1264 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1265 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1266
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1267 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1268
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1269 #region ConvertElementAt
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1270
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1271 Expression ConvertElementAt(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1272 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1273 var sequence = OptimizeExpression(method.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1274 var index = OptimizeExpression(method.Arguments[1]).Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1275 var sourceType = method.Method.GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1276
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1277 MethodInfo skipMethod;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1278
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1279 if (index.NodeType == ExpressionType.Lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1280 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1281 skipMethod = ReflectionHelper.Expressor<object>.MethodExpressor(o => LinqExtensions.Skip<object>(null, null));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1282 skipMethod = skipMethod.GetGenericMethodDefinition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1283 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1284 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1285 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1286 skipMethod = GetQueriableMethodInfo(method, (mi,_) => mi.Name == "Skip");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1287 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1288
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1289 skipMethod = skipMethod.MakeGenericMethod(sourceType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1290
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1291 var methodName = method.Method.Name == "ElementAt" ? "First" : "FirstOrDefault";
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1292 var firstMethod = GetQueriableMethodInfo(method, (mi,_) => mi.Name == methodName && mi.GetParameters().Length == 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1293
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1294 firstMethod = firstMethod.MakeGenericMethod(sourceType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1295
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1296 return Expression.Call(null, firstMethod, Expression.Call(null, skipMethod, sequence, index));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1297 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1298
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1299 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1300
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1301 #region Helpers
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1302
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1303 MethodInfo GetQueriableMethodInfo(MethodCallExpression method, Func<MethodInfo,bool,bool> predicate)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1304 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1305 return method.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1306 EnumerableMethods.FirstOrDefault(m => predicate(m, false)) ?? EnumerableMethods.First(m => predicate(m, true)):
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1307 QueryableMethods. FirstOrDefault(m => predicate(m, false)) ?? QueryableMethods. First(m => predicate(m, true));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1308 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1309
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1310 MethodInfo GetMethodInfo(MethodCallExpression method, string name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1311 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1312 return method.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1313 EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1314 .Where(m => m.Name == name && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1315 .First(m => m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1316 QueryableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1317 .Where(m => m.Name == name && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1318 .First(m => m.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1319 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1320
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1321 static Type[] GetMethodGenericTypes(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1322 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1323 return method.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1324 method.Method.GetParameters()[1].ParameterType.GetGenericArguments() :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1325 method.Method.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1326 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1327
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1328 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1329
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1330 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1331 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1332 }