0
|
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 }
|