annotate Source/Data/Linq/Builder/ExpressionBuilder.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children f7d63a092920
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();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
695 var genericType = sequence.Type.GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
696 var newMethod = methodInfo.MakeGenericMethod(genericType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
697
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
698 method = Expression.Call(newMethod, sequence, predicate);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
699
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
700 if (exprs.Count > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
701 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
702 var parameter = Expression.Parameter(expr.Type, lparam.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
703
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
704 methodInfo = GetMethodInfo(method, "Select");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
705 methodInfo = methodInfo.MakeGenericMethod(expr.Type, lparam.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
706 method = Expression.Call(methodInfo, method,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
707 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
708 exprs.Aggregate((Expression)parameter, (current,_) => Expression.PropertyOrField(current, "p")),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
709 parameter));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
710 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
711 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
712
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
713 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
714 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
715
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
716 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
717
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
718 #region ConvertGroupBy
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
719
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
720 public class GroupSubQuery<TKey,TElement>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
721 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
722 public TKey Key;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
723 public TElement Element;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
724 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
725
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
726 interface IGroupByHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
727 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
728 void Set(bool wrapInSubQuery, Expression sourceExpression, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
729
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
730 Expression AddElementSelectorQ ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
731 Expression AddElementSelectorE ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
732 Expression AddResultQ ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
733 Expression AddResultE ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
734 Expression WrapInSubQueryQ ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
735 Expression WrapInSubQueryE ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
736 Expression WrapInSubQueryResultQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
737 Expression WrapInSubQueryResultE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
738 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
739
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
740 class GroupByHelper<TSource,TKey,TElement,TResult> : IGroupByHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
741 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
742 bool _wrapInSubQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
743 Expression _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
744 LambdaExpression _keySelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
745 LambdaExpression _elementSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
746 LambdaExpression _resultSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
747
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
748 public void Set(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
749 bool wrapInSubQuery,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
750 Expression sourceExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
751 LambdaExpression keySelector,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
752 LambdaExpression elementSelector,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
753 LambdaExpression resultSelector)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
754 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
755 _wrapInSubQuery = wrapInSubQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
756 _sourceExpression = sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
757 _keySelector = keySelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
758 _elementSelector = elementSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
759 _resultSelector = resultSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
760 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
761
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
762 public Expression AddElementSelectorQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
763 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
764 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<IGrouping<TKey,TSource>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
765 .GroupBy(keyParam => key, _ => _)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
766 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
767
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
768 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
769 var keyArg = GetLambda(body, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
770
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
771 return Convert(func, keyArg, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
772 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
773
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
774 public Expression AddElementSelectorE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
775 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
776 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<IGrouping<TKey,TSource>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
777 .GroupBy(keyParam => key, _ => _)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
778 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
779
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
780 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
781 var keyArg = GetLambda(body, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
782
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
783 return Convert(func, keyArg, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
784 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
785
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
786 public Expression AddResultQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
787 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
788 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
789 .GroupBy(keyParam => key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
790 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
791 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
792
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
793 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
794 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
795 var elemArg = GetLambda(body, 0, 2).Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
796 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
797
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
798 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
799 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
800
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
801 public Expression AddResultE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
802 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
803 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
804 .GroupBy(keyParam => key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
805 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
806 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
807
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
808 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
809 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .GroupBy(keyParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
810 var elemArg = GetLambda(body, 0, 2).Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
811 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
812
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
813 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
814 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
815
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
816 public Expression WrapInSubQueryQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
817 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
818 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<IGrouping<TKey,TElement>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
819 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
820 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
821 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
822 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
823 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
824 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
825 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
826
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
827 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
828 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
829 var elemArg = GetLambda(body, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
830
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
831 return Convert(func, keyArg, elemArg, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
832 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
833
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
834 public Expression WrapInSubQueryE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
835 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
836 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<IGrouping<TKey,TElement>>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
837 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
838 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
839 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
840 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
841 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
842 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
843 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
844
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
845 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
846 var keyArg = GetLambda(body, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
847 var elemArg = GetLambda(body, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
848
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
849 return Convert(func, keyArg, elemArg, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
850 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
851
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
852 public Expression WrapInSubQueryResultQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
853 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
854 Expression<Func<IQueryable<TSource>,TKey,TElement,TResult,IQueryable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
855 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
856 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
857 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
858 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
859 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
860 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
861 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
862 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
863
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
864 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
865 var keyArg = GetLambda(body, 0, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
866 var elemArg = GetLambda(body, 0, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
867 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
868
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
869 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
870 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
871
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
872 public Expression WrapInSubQueryResultE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
873 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
874 Expression<Func<IEnumerable<TSource>,TKey,TElement,TResult,IEnumerable<TResult>>> func = (source,key,e,r) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
875 .Select(selectParam => new GroupSubQuery<TKey,TSource>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
876 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
877 Key = key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
878 Element = selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
879 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
880 .GroupBy(_ => _.Key, elemParam => e)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
881 .Select (resParam => r)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
882 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
883
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
884 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
885 var keyArg = GetLambda(body, 0, 0, 1).Parameters[0]; // .Select (selectParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
886 var elemArg = GetLambda(body, 0, 2). Parameters[0]; // .GroupBy(..., elemParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
887 var resArg = GetLambda(body, 1). Parameters[0]; // .Select (resParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
888
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
889 return Convert(func, keyArg, elemArg, resArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
890 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
891
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
892 Expression Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
893 LambdaExpression func,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
894 ParameterExpression keyArg,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
895 ParameterExpression elemArg,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
896 ParameterExpression resArg)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
897 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
898 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
899 var expr = body.Convert(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
900 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
901 if (ex == func.Parameters[0])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
902 return _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
903
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
904 if (ex == func.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
905 return _keySelector.Body.Convert(e => e == _keySelector.Parameters[0] ? keyArg : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
906
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
907 if (ex == func.Parameters[2])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
908 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
909 Expression obj = elemArg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
910
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
911 if (_wrapInSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
912 obj = Expression.PropertyOrField(elemArg, "Element");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
913
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
914 if (_elementSelector == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
915 return obj;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
916
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
917 return _elementSelector.Body.Convert(e => e == _elementSelector.Parameters[0] ? obj : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
918 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
919
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
920 if (ex == func.Parameters[3])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
921 return _resultSelector.Body.Convert(e =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
922 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
923 if (e == _resultSelector.Parameters[0])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
924 return Expression.PropertyOrField(resArg, "Key");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
925
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
926 if (e == _resultSelector.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
927 return resArg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
928
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
929 return e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
930 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
931
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
932 return ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
933 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
934
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
935 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
936 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
937 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
938
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
939 static LambdaExpression GetLambda(Expression expression, params int[] n)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
940 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
941 foreach (var i in n)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
942 expression = ((MethodCallExpression)expression).Arguments[i].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
943 return (LambdaExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
944 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
945
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
946 Expression ConvertGroupBy(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
947 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
948 if (method.Arguments[method.Arguments.Count - 1].Unwrap().NodeType != ExpressionType.Lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
949 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
950
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
951 var types = method.Method.GetGenericMethodDefinition().GetGenericArguments()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
952 .Zip(method.Method.GetGenericArguments(), (n, t) => new { n = n.Name, t })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
953 .ToDictionary(_ => _.n, _ => _.t);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
954
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
955 var sourceExpression = OptimizeExpression(method.Arguments[0].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
956 var keySelector = (LambdaExpression)OptimizeExpression(method.Arguments[1].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
957 var elementSelector = types.ContainsKey("TElement") ? (LambdaExpression)OptimizeExpression(method.Arguments[2].Unwrap()) : null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
958 var resultSelector = types.ContainsKey("TResult") ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
959 (LambdaExpression)OptimizeExpression(method.Arguments[types.ContainsKey("TElement") ? 3 : 2].Unwrap()) : null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
960
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
961 var needSubQuery = null != ConvertExpression(keySelector.Body.Unwrap()).Find(IsExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
962
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
963 if (!needSubQuery && resultSelector == null && elementSelector != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
964 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
965
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
966 var gtype = typeof(GroupByHelper<,,,>).MakeGenericType(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
967 types["TSource"],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
968 types["TKey"],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
969 types.ContainsKey("TElement") ? types["TElement"] : types["TSource"],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
970 types.ContainsKey("TResult") ? types["TResult"] : types["TSource"]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
971
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
972 var helper =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
973 //Expression.Lambda<Func<IGroupByHelper>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
974 // Expression.Convert(Expression.New(gtype), typeof(IGroupByHelper)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
975 //.Compile()();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
976 (IGroupByHelper)Activator.CreateInstance(gtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
977
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
978 helper.Set(needSubQuery, sourceExpression, keySelector, elementSelector, resultSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
979
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
980 if (method.Method.DeclaringType == typeof(Queryable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
981 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
982 if (!needSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
983 return resultSelector == null ? helper.AddElementSelectorQ() : helper.AddResultQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
984
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
985 return resultSelector == null ? helper.WrapInSubQueryQ() : helper.WrapInSubQueryResultQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
986 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
987 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
988 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
989 if (!needSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
990 return resultSelector == null ? helper.AddElementSelectorE() : helper.AddResultE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
991
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
992 return resultSelector == null ? helper.WrapInSubQueryE() : helper.WrapInSubQueryResultE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
993 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
994 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
995
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
996 bool IsExpression(Expression ex)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
997 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
998 switch (ex.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
999 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1000 case ExpressionType.Convert :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1001 case ExpressionType.ConvertChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1002 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1003 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1004 case ExpressionType.NewArrayBounds :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1005 case ExpressionType.NewArrayInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1006 case ExpressionType.Parameter : return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1007 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1008 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1009 var ma = (MemberExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1010 var attr = GetFunctionAttribute(ma.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1011
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1012 if (attr != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1013 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1014
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1015 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1016 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1017 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1018
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1019 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1020 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1021
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1022 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1023
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1024 #region ConvertSelectMany
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1025
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1026 interface ISelectManyHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1027 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1028 void Set(Expression sourceExpression, LambdaExpression colSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1029
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1030 Expression AddElementSelectorQ();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1031 Expression AddElementSelectorE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1032 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1033
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1034 class SelectManyHelper<TSource,TCollection> : ISelectManyHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1035 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1036 Expression _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1037 LambdaExpression _colSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1038
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1039 public void Set(Expression sourceExpression, LambdaExpression colSelector)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1040 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1041 _sourceExpression = sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1042 _colSelector = colSelector;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1043 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1044
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1045 public Expression AddElementSelectorQ()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1046 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1047 Expression<Func<IQueryable<TSource>,IEnumerable<TCollection>,IQueryable<TCollection>>> func = (source,col) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1048 .SelectMany(colParam => col, (s,c) => c)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1049 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1050
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1051 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1052 var colArg = GetLambda(body, 1).Parameters[0]; // .SelectMany(colParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1053
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1054 return Convert(func, colArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1055 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1056
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1057 public Expression AddElementSelectorE()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1058 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1059 Expression<Func<IEnumerable<TSource>,IEnumerable<TCollection>,IEnumerable<TCollection>>> func = (source,col) => source
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1060 .SelectMany(colParam => col, (s,c) => c)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1061 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1062
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1063 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1064 var colArg = GetLambda(body, 1).Parameters[0]; // .SelectMany(colParam
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1065
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1066 return Convert(func, colArg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1067 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1068
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1069 Expression Convert(LambdaExpression func, ParameterExpression colArg)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1070 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1071 var body = func.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1072 var expr = body.Convert(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1073 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1074 if (ex == func.Parameters[0])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1075 return _sourceExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1076
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1077 if (ex == func.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1078 return _colSelector.Body.Convert(e => e == _colSelector.Parameters[0] ? colArg : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1079
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1080 return ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1081 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1082
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1083 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1084 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1085 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1086
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1087 Expression ConvertSelectMany(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1088 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1089 if (method.Arguments.Count != 2 || ((LambdaExpression)method.Arguments[1].Unwrap()).Parameters.Count != 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1090 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1091
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1092 var types = method.Method.GetGenericMethodDefinition().GetGenericArguments()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1093 .Zip(method.Method.GetGenericArguments(), (n, t) => new { n = n.Name, t })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1094 .ToDictionary(_ => _.n, _ => _.t);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1095
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1096 var sourceExpression = OptimizeExpression(method.Arguments[0].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1097 var colSelector = (LambdaExpression)OptimizeExpression(method.Arguments[1].Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1098
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1099 var gtype = typeof(SelectManyHelper<,>).MakeGenericType(types["TSource"], types["TResult"]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1100 var helper =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1101 //Expression.Lambda<Func<ISelectManyHelper>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1102 // Expression.Convert(Expression.New(gtype), typeof(ISelectManyHelper)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1103 //.Compile()();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1104 (ISelectManyHelper)Activator.CreateInstance(gtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1105
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1106 helper.Set(sourceExpression, colSelector);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1107
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1108 return method.Method.DeclaringType == typeof(Queryable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1109 helper.AddElementSelectorQ() :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1110 helper.AddElementSelectorE();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1111 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1112
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1113 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1114
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1115 #region ConvertPredicate
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1116
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1117 Expression ConvertPredicate(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1118 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1119 if (method.Arguments.Count != 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1120 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1121
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1122 var cm = GetQueriableMethodInfo(method, (m,_) => m.Name == method.Method.Name && m.GetParameters().Length == 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1123 var wm = GetMethodInfo(method, "Where");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1124
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1125 var argType = method.Method.GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1126
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1127 wm = wm.MakeGenericMethod(argType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1128 cm = cm.MakeGenericMethod(argType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1129
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1130 return Expression.Call(null, cm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1131 Expression.Call(null, wm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1132 OptimizeExpression(method.Arguments[0]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1133 OptimizeExpression(method.Arguments[1])));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1134 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1136 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1137
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1138 #region ConvertSelector
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1139
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1140 Expression ConvertSelector(MethodCallExpression method, bool isGeneric)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1141 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1142 if (method.Arguments.Count != 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1143 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1144
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1145 isGeneric = isGeneric && method.Method.DeclaringType == typeof(Queryable);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1146
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1147 var types = GetMethodGenericTypes(method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1148 var sm = GetMethodInfo(method, "Select");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1149 var cm = GetQueriableMethodInfo(method, (m,isDefault) =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1150 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1151 if (m.Name == method.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1152 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1153 var ps = m.GetParameters();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1154
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1155 if (ps.Length == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1156 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1157 if (isGeneric)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1158 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1159
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1160 var ts = ps[0].ParameterType.GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1161 return ts[0] == types[1] || isDefault && ts[0].IsGenericParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1162 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1163 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1164
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1165 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1166 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1167
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1168 var argType = types[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1169
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1170 sm = sm.MakeGenericMethod(argType, types[1]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1171
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1172 if (cm.IsGenericMethodDefinition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1173 cm = cm.MakeGenericMethod(types[1]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1174
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1175 return Expression.Call(null, cm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1176 OptimizeExpression(Expression.Call(null, sm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1177 method.Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1178 method.Arguments[1])));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1179 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1180
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1181 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1182
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1183 #region ConvertSelect
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1184
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1185 Expression ConvertSelect(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1186 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1187 var sequence = OptimizeExpression(method.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1188 var lambda1 = (LambdaExpression)method.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1189 var lambda = (LambdaExpression)OptimizeExpression(lambda1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1190
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1191 if (lambda1.Parameters.Count > 1 ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1192 sequence.NodeType != ExpressionType.Call ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1193 ((MethodCallExpression)sequence).Method.Name != method.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1194 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1195 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1196 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1197
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1198 var slambda = (LambdaExpression)((MethodCallExpression)sequence).Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1199 var sbody = slambda.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1200
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1201 if (slambda.Parameters.Count > 1 || sbody.NodeType != ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1202 return method;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1203
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1204 var types1 = GetMethodGenericTypes((MethodCallExpression)sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1205 var types2 = GetMethodGenericTypes(method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1206
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1207 var expr = Expression.Call(null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1208 GetMethodInfo(method, "Select").MakeGenericMethod(types1[0], types2[1]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1209 ((MethodCallExpression)sequence).Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1210 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1211 lambda.Body.Convert(ex => ex == lambda.Parameters[0] ? sbody : ex),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1212 slambda.Parameters[0]));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1213
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1214 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1215 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1216
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1217 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1218
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1219 #region ConvertIQueriable
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1220
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1221 Expression ConvertIQueriable(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1222 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1223 if (expression.NodeType == ExpressionType.MemberAccess || expression.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1224 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1225 var p = Expression.Parameter(typeof(Expression), "exp");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1226 var exas = expression.GetExpressionAccessors(p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1227 var expr = ReplaceParameter(exas, expression, _ => {});
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1228
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1229 if (expr.Find(e => e.NodeType == ExpressionType.Parameter && e != p) != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1230 return expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1231
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1232 var l = Expression.Lambda<Func<Expression,IQueryable>>(Expression.Convert(expr, typeof(IQueryable)), new [] { p });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1233 var n = _query.AddQueryableAccessors(expression, l);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1234
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1235 Expression accessor;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1236
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1237 _expressionAccessors.TryGetValue(expression, out accessor);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1238
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1239 var path =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1240 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1241 Expression.Constant(_query),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1242 ReflectionHelper.Expressor<Query>.MethodExpressor(a => a.GetIQueryable(0, null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1243 new[] { Expression.Constant(n), accessor ?? Expression.Constant(null, typeof(Expression)) });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1244
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1245 var qex = _query.GetIQueryable(n, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1246
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1247 if (expression.NodeType == ExpressionType.Call && qex.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1248 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1249 var m1 = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1250 var m2 = (MethodCallExpression)qex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1251
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1252 if (m1.Method == m2.Method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1253 return expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1254 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1255
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1256 foreach (var a in qex.GetExpressionAccessors(path))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1257 if (!_expressionAccessors.ContainsKey(a.Key))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1258 _expressionAccessors.Add(a.Key, a.Value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1259
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1260 return qex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1261 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1262
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1263 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1264 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1265
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1266 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1267
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1268 #region ConvertElementAt
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1269
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1270 Expression ConvertElementAt(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1271 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1272 var sequence = OptimizeExpression(method.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1273 var index = OptimizeExpression(method.Arguments[1]).Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1274 var sourceType = method.Method.GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1275
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1276 MethodInfo skipMethod;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1277
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1278 if (index.NodeType == ExpressionType.Lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1279 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1280 skipMethod = ReflectionHelper.Expressor<object>.MethodExpressor(o => LinqExtensions.Skip<object>(null, null));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1281 skipMethod = skipMethod.GetGenericMethodDefinition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1282 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1283 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1284 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1285 skipMethod = GetQueriableMethodInfo(method, (mi,_) => mi.Name == "Skip");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1286 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1287
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1288 skipMethod = skipMethod.MakeGenericMethod(sourceType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1289
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1290 var methodName = method.Method.Name == "ElementAt" ? "First" : "FirstOrDefault";
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1291 var firstMethod = GetQueriableMethodInfo(method, (mi,_) => mi.Name == methodName && mi.GetParameters().Length == 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1292
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1293 firstMethod = firstMethod.MakeGenericMethod(sourceType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1294
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1295 return Expression.Call(null, firstMethod, Expression.Call(null, skipMethod, sequence, index));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1296 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1297
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1298 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1299
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1300 #region Helpers
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1301
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1302 MethodInfo GetQueriableMethodInfo(MethodCallExpression method, Func<MethodInfo,bool,bool> predicate)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1303 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1304 return method.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1305 EnumerableMethods.FirstOrDefault(m => predicate(m, false)) ?? EnumerableMethods.First(m => predicate(m, true)):
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1306 QueryableMethods. FirstOrDefault(m => predicate(m, false)) ?? QueryableMethods. First(m => predicate(m, true));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1307 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1308
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1309 MethodInfo GetMethodInfo(MethodCallExpression method, string name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1310 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1311 return method.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1312 EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1313 .Where(m => m.Name == name && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1314 .First(m => m.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1315 QueryableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1316 .Where(m => m.Name == name && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1317 .First(m => m.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1318 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1319
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1320 static Type[] GetMethodGenericTypes(MethodCallExpression method)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1321 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1322 return method.Method.DeclaringType == typeof(Enumerable) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1323 method.Method.GetParameters()[1].ParameterType.GetGenericArguments() :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1324 method.Method.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1325 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1326
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1327 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1328
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1329 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1330 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1331 }