Mercurial > pub > bltoolkit
comparison Source/Data/Linq/Builder/MethodCallBuilder.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Linq; | |
3 using System.Linq.Expressions; | |
4 | |
5 namespace BLToolkit.Data.Linq.Builder | |
6 { | |
7 using BLToolkit.Linq; | |
8 | |
9 abstract class MethodCallBuilder : ISequenceBuilder | |
10 { | |
11 public int BuildCounter { get; set; } | |
12 | |
13 public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo) | |
14 { | |
15 if (buildInfo.Expression.NodeType == ExpressionType.Call) | |
16 return CanBuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo); | |
17 return false; | |
18 } | |
19 | |
20 public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo) | |
21 { | |
22 return BuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo); | |
23 } | |
24 | |
25 public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param) | |
26 { | |
27 return Convert(builder, (MethodCallExpression)buildInfo.Expression, buildInfo, param); | |
28 } | |
29 | |
30 public bool IsSequence(ExpressionBuilder builder, BuildInfo buildInfo) | |
31 { | |
32 return builder.IsSequence(new BuildInfo(buildInfo, ((MethodCallExpression)buildInfo.Expression).Arguments[0])); | |
33 } | |
34 | |
35 protected abstract bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo); | |
36 protected abstract IBuildContext BuildMethodCall (ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo); | |
37 protected abstract SequenceConvertInfo Convert (ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param); | |
38 | |
39 protected static Expression ConvertMethod( | |
40 MethodCallExpression methodCall, | |
41 int sourceTypeNumber, | |
42 SequenceConvertInfo info, | |
43 ParameterExpression param, | |
44 Expression expression) | |
45 { | |
46 if (expression == methodCall && param != null && param.Type != info.Parameter.Type) | |
47 { | |
48 var types = methodCall.Method.GetGenericArguments(); | |
49 var mgen = methodCall.Method.GetGenericMethodDefinition(); | |
50 | |
51 types[sourceTypeNumber] = info.Parameter.Type; | |
52 | |
53 var args = methodCall.Arguments.ToArray(); | |
54 | |
55 args[0] = info.Expression; | |
56 | |
57 for (var i = 1; i < args.Length; i++) | |
58 { | |
59 var arg = args[i].Unwrap(); | |
60 | |
61 if (arg.NodeType == ExpressionType.Lambda) | |
62 { | |
63 var l = (LambdaExpression)arg; | |
64 | |
65 if (l.Parameters.Any(a => a == param)) | |
66 { | |
67 args[i] = Expression.Lambda( | |
68 l.Body.Convert(ex => ConvertMethod(methodCall, sourceTypeNumber, info, param, ex)), | |
69 info.Parameter); | |
70 | |
71 return Expression.Call(methodCall.Object, mgen.MakeGenericMethod(types), args); | |
72 } | |
73 } | |
74 } | |
75 } | |
76 | |
77 if (expression == methodCall.Arguments[0]) | |
78 return info.Expression; | |
79 | |
80 switch (expression.NodeType) | |
81 { | |
82 case ExpressionType.Parameter : | |
83 | |
84 if (info.ExpressionsToReplace != null) | |
85 foreach (var item in info.ExpressionsToReplace) | |
86 if (expression == item.Path || expression == param && item.Path.NodeType == ExpressionType.Parameter) | |
87 return item.Expr; | |
88 break; | |
89 | |
90 case ExpressionType.MemberAccess : | |
91 | |
92 if (info.ExpressionsToReplace != null) | |
93 { | |
94 foreach (var item in info.ExpressionsToReplace) | |
95 { | |
96 var ex1 = expression; | |
97 var ex2 = item.Path; | |
98 | |
99 while (ex1.NodeType == ex2.NodeType) | |
100 { | |
101 if (ex1.NodeType == ExpressionType.Parameter) | |
102 return ex1 == ex2 || info.Parameter == ex2? item.Expr : expression; | |
103 | |
104 if (ex2.NodeType != ExpressionType.MemberAccess) | |
105 break; | |
106 | |
107 var ma1 = (MemberExpression)ex1; | |
108 var ma2 = (MemberExpression)ex2; | |
109 | |
110 if (ma1.Member != ma2.Member) | |
111 break; | |
112 | |
113 ex1 = ma1.Expression; | |
114 ex2 = ma2.Expression; | |
115 } | |
116 } | |
117 } | |
118 | |
119 break; | |
120 } | |
121 | |
122 return expression; | |
123 } | |
124 } | |
125 } |