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