annotate Source/Data/Linq/Builder/SelectBuilder.cs @ 6:11b6da379593

Исправлена странная ошибка при использовании OfType<...>().Where(...)
author cin
date Mon, 05 Dec 2016 05:50:52 +0300
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Data;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 using Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 class SelectBuilder : MethodCallBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 #region SelectBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 if (methodCall.IsQueryable("Select"))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 switch (((LambdaExpression)methodCall.Arguments[1].Unwrap()).Parameters.Count)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 case 1 :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 case 2 : return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 default: break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 var selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 sequence.SetAlias(selector.Parameters[0].Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 var body = selector.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 switch (body.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 case ExpressionType.Parameter : break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 default :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 sequence = CheckSubQueryForSelect(sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 var context = selector.Parameters.Count == 1 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 new SelectContext (buildInfo.Parent, selector, sequence) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 new SelectContext2(buildInfo.Parent, selector, sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 #if DEBUG
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 context.MethodCall = methodCall;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 #endif
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 return context;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 static IBuildContext CheckSubQueryForSelect(IBuildContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 return context.SqlQuery.Select.IsDistinct ? new SubQueryContext(context) : context;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 #region SelectContext2
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 class SelectContext2 : SelectContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 public SelectContext2(IBuildContext parent, LambdaExpression lambda, IBuildContext sequence)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 : base(parent, lambda, sequence)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 static readonly ParameterExpression _counterParam = Expression.Parameter(typeof(int), "counter");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 var expr = BuildExpression(null, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 if (expr.Type != typeof(T))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 expr = Expression.Convert(expr, typeof(T));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 var mapper = Expression.Lambda<Func<int,QueryContext,IDataContext,IDataReader,Expression,object[],T>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 Builder.BuildBlock(expr), new []
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 _counterParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 ExpressionBuilder.ContextParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 ExpressionBuilder.DataContextParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 ExpressionBuilder.DataReaderParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 ExpressionBuilder.ExpressionParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 ExpressionBuilder.ParametersParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 var func = mapper.Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 Func<QueryContext,IDataContext,IDataReader,Expression,object[],int,T> map = (ctx,db,rd,e,ps,n) => func(n, ctx, db, rd, e, ps);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 query.SetQuery(map);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 switch (requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 case RequestFor.Expression :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 case RequestFor.Root :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 if (expression == Lambda.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 return IsExpressionResult.True;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 return base.IsExpression(expression, level, requestFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 public override Expression BuildExpression(Expression expression, int level)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 if (expression == Lambda.Parameters[1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 return _counterParam;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 return base.BuildExpression(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 #region Convert
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 protected override SequenceConvertInfo Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 ExpressionBuilder builder, MethodCallExpression originalMethodCall, BuildInfo buildInfo, ParameterExpression param)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 var methodCall = originalMethodCall;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 var selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135 var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), selector.Parameters[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 if (info != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 methodCall = (MethodCallExpression)methodCall.Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 ex => ConvertMethod(methodCall, 0, info, selector.Parameters[0], ex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 if (param != null && param != builder.SequenceParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 var list =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 (
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 from path in GetExpressions(selector.Parameters[0], param, 0, selector.Body.Unwrap())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 orderby path.Level descending
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150 select path
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 ).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 if (list.Count > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 var plist = list.Where(e => e.Expr == selector.Parameters[0]).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 if (plist.Count > 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 list = list.Except(plist.Skip(1)).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 var p = plist.FirstOrDefault();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 if (p == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 var types = methodCall.Method.GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 var mgen = methodCall.Method.GetGenericMethodDefinition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 var btype = typeof(ExpressionHoder<,>).MakeGenericType(types[0], selector.Body.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 var fields = btype.GetFields();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 var pold = selector.Parameters[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 var psel = Expression.Parameter(types[0], pold.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 methodCall = Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 methodCall.Object,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 mgen.MakeGenericMethod(types[0], btype),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 methodCall.Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 Expression.MemberInit(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 Expression.New(btype),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 Expression.Bind(fields[0], psel),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179 Expression.Bind(fields[1], selector.Body.Convert(e => e == pold ? psel : e))),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 psel));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 selector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 param = Expression.Parameter(selector.Body.Type, param.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 list.Add(new SequenceConvertPath { Path = param, Expr = Expression.MakeMemberAccess(param, fields[1]), Level = 1 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 var expr = Expression.MakeMemberAccess(param, fields[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 foreach (var t in list)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 t.Expr = t.Expr.Convert(ex => ex == pold ? expr : ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 return new SequenceConvertInfo
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194 Parameter = param,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 Expression = methodCall,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 ExpressionsToReplace = list
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 if (info != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 if (info.ExpressionsToReplace != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 foreach (var path in info.ExpressionsToReplace)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206 path.Path = path.Path.Convert(e => e == info.Parameter ? p.Path : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 path.Expr = path.Expr.Convert(e => e == info.Parameter ? p.Path : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208 path.Level += p.Level;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 list.Add(path);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 list = list.OrderByDescending(path => path.Level).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217 if (list.Count > 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 return new SequenceConvertInfo
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221 Parameter = param,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 Expression = methodCall,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 ExpressionsToReplace = list
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224 .Where (e => e != p)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 .Select(ei =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 ei.Expr = ei.Expr.Convert(e => e == p.Expr ? p.Path : e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228 return ei;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 .ToList()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 if (methodCall != originalMethodCall)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 return new SequenceConvertInfo
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 Parameter = param,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 Expression = methodCall,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 static IEnumerable<SequenceConvertPath> GetExpressions(ParameterExpression param, Expression path, int level, Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 // new { ... }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 var expr = (NewExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 if (expr.Members != null) for (var i = 0; i < expr.Members.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258 var q = GetExpressions(param, Expression.MakeMemberAccess(path, expr.Members[i]), level + 1, expr.Arguments[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 foreach (var e in q)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 yield return e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 // new MyObject { ... }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 var expr = (MemberInitExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271 var dic = TypeAccessor.GetAccessor(expr.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272 .Select((m,i) => new { m, i })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 .ToDictionary(_ => _.m.MemberInfo.Name, _ => _.i);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 foreach (var binding in expr.Bindings.Cast<MemberAssignment>().OrderBy(b => dic[b.Member.Name]))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 var q = GetExpressions(param, Expression.MakeMemberAccess(path, binding.Member), level + 1, binding.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278 foreach (var e in q)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279 yield return e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285 // parameter
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 if (expression == param)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 yield return new SequenceConvertPath { Path = path, Expr = expression, Level = level };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 case ExpressionType.TypeAs :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 yield return new SequenceConvertPath { Path = path, Expr = expression, Level = level };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296 // Queriable method.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300 var call = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 if (call.IsQueryable())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303 if (TypeHelper.IsSameOrParent(typeof(IEnumerable), call.Type) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 TypeHelper.IsSameOrParent(typeof(IQueryable), call.Type) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 FirstSingleBuilder.MethodNames.Contains(call.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 yield return new SequenceConvertPath { Path = path, Expr = expression, Level = level };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 }