/// <summary> /// 访问指定的方法 /// </summary> /// <param name="theEntityType">实体的类型</param> /// <param name="m">访问方法调用相关的表达式</param> /// <param name="tableAlias">表的别名</param> /// <param name="colConditionParts">存储条件节点的栈</param> /// <param name="colParameterNames">存储参数名称的列表</param> /// <param name="colDbTypes">存储数据库字段类型的列表</param> /// <param name="colArguments">存储条件值的列表</param> public static void Visit(Type theEntityType, MethodCallExpression m, string tableAlias, Stack<string> colConditionParts, List<string> colParameterNames, List<DbType> colDbTypes, List<object> colArguments) { if (m.Object is MemberExpression) { //类似n.Name.StartsWith("吴")这样的调用 if (m.Object.Type == typeof(string)) { StringMethodCallVisitor.Visit(theEntityType, m, tableAlias, colConditionParts, colParameterNames, colDbTypes, colArguments); } else { throw new Exception("暂不支持{" + m.ToString() + "}的调用!"); } } else if (m.Object is ConstantExpression) { //类似"ABCD".Contains(n.Name)这样的调用 var cons = m.Object as ConstantExpression; if (cons.Type == typeof(string)) { StringMethodCallVisitor.Visit(theEntityType, m, tableAlias, colConditionParts, colParameterNames, colDbTypes, colArguments); } else { throw new Exception("暂不支持{" + m.ToString() + "}的调用!"); } } else { throw new Exception("暂不支持{" + m.ToString() + "}的调用!"); } }
public Expression Bind(ProjectionExpression projection, ProjectionBindingContext context, MethodCallExpression node, IEnumerable<Expression> arguments) { var collectionLambda = ExtensionExpressionVisitor.GetLambda(arguments.First()); var binder = new AccumulatorBinder(context.GroupMap, context.SerializerRegistry); binder.RegisterParameterReplacement(collectionLambda.Parameters[0], projection.Projector); var collectionSelector = binder.Bind(collectionLambda.Body) as SerializationExpression; if (collectionSelector == null) { var message = string.Format("Unable to determine the collection selector in the tree: {0}", node.ToString()); throw new NotSupportedException(message); } var collectionArraySerializer = collectionSelector.SerializationInfo.Serializer as IBsonArraySerializer; BsonSerializationInfo collectionItemSerializationInfo; if (collectionArraySerializer == null || !collectionArraySerializer.TryGetItemSerializationInfo(out collectionItemSerializationInfo)) { var message = string.Format("The collection selector's serializer must implement IBsonArraySerializer: {0}", node.ToString()); throw new NotSupportedException(message); } Expression resultSelector; if (arguments.Count() == 2) { var resultLambda = ExtensionExpressionVisitor.GetLambda(arguments.Last()); binder.RegisterParameterReplacement(resultLambda.Parameters[0], projection.Projector); binder.RegisterParameterReplacement( resultLambda.Parameters[1], new SerializationExpression( resultLambda.Parameters[1], collectionItemSerializationInfo.WithNewName(collectionSelector.SerializationInfo.ElementName))); resultSelector = binder.Bind(resultLambda.Body); } else { resultSelector = new SerializationExpression( collectionSelector, collectionItemSerializationInfo.WithNewName(collectionSelector.SerializationInfo.ElementName)); } var projector = BuildProjector(resultSelector, context); return new ProjectionExpression( new SelectManyExpression( projection.Source, collectionSelector, resultSelector), projector); }
protected override Expression VisitMethodCall(MethodCallExpression node) { Expression retExpr = null; if (node.Method.Name == _functionName) { var str = node.ToString(); MethodCall call; if (_methodCalls.TryGetValue(str, out call)) { ++call.CallCount; } else { call = new MethodCall(node, Expression.Parameter(node.Type, "param" + (_methodCalls.Count))); _methodCalls.Add(str, call); } retExpr = call.Parameter; } else retExpr = base.VisitMethodCall(node); return retExpr; }
protected override Expression VisitMethodCall(MethodCallExpression m) { string s = m.ToString(); // VB.net : e.g. CompareString(x.NoCase, "Me 4", False) if(s.StartsWith("CompareString")) { var left = m.Arguments[0]; // Removes dot if any var leftStr = left.ToString().Substring(left.ToString().IndexOf('.') + 1); var right = m.Arguments[1].ToString().Replace("\"", String.Empty); RDBExpression exp = RDBExpression.Equal; _bitmap.Push(qexpression("" + leftStr, exp, right)); return null; } string mc = s.Substring(s.IndexOf('.') + 1); if (mc.Contains("Between")) { // TODO : add code for between parsing here string name = m.Arguments[0].ToString().Split('.')[1]; object from = GetValueForMember(m.Arguments[1]); object to = GetValueForMember(m.Arguments[2]); //var bits = qfromto(name, from, to); } else _stack.Push(mc); return m; }
internal override Expression VisitMethodCall(MethodCallExpression m) { /* if ((m.Object != null && ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(m.Object)) || m.Arguments.Any(a => ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(a))) { throw new NotSupportedException(string.Format(SR.ALinqExpressionNotSupportedInProjection, this.type, m.ToString())); } */ if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m)) { ProjectionAnalyzer.CheckChainedSequence(m, this.type); return base.VisitMethodCall(m); } throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjectionToEntity, this.type, m.ToString())); }
/// <summary> /// Translate the method call /// </summary> /// <param name="expr"></param> /// <param name="result"></param> /// <param name="gc"></param> /// <param name="context"></param> /// <returns></returns> public IValue CodeMethodCall(MethodCallExpression expr, IGeneratedQueryCode gc, CompositionContainer container) { Init(); /// /// First see if we can't locate the method call that at least matches in names /// var matchingMethodNames = from kt in _knownTypes where kt.Name == expr.Method.DeclaringType.Name from m in kt.Methods where m.Name == expr.Method.Name select new { theType = kt, theMethod = m }; /// /// Next, match with the arguments /// var matchingMethod = from m in matchingMethodNames where m.theMethod.Arguments.Length == expr.Arguments.Count where m.theMethod.Arguments.Zip(expr.Arguments, (us, them) => new Tuple<KnownTypeInfo.MechodArg, Expression>(us, them)).All(apair => apair.Item1.Type == apair.Item2.Type.FullName) select m; /// /// Ok, at this point, we should have only one guy. If we have more then just choose the first /// var method = matchingMethod.FirstOrDefault(); if (method == null) throw new ArgumentException("Could not find a matching method to translate for the call " + expr.ToString()); /// /// And now translate the call /// StringBuilder rawValue = new StringBuilder(); rawValue.Append(method.theMethod.CPPName); rawValue.Append("("); bool first = true; var dependents = Enumerable.Empty<IDeclaredParameter>(); foreach (var arg in expr.Arguments.Zip(method.theMethod.Arguments, (m, a) => Tuple.Create(m, a))) { if (!first) rawValue.Append(","); first = false; var e = ExpressionToCPP.InternalGetExpression(arg.Item1, gc, null, container); rawValue.AppendFormat("({0}){1}", arg.Item2.CPPType, e.RawValue); dependents = dependents.Concat(e.Dependants); } rawValue.Append(")"); var result = new ValSimple(rawValue.ToString(), expr.Type, dependents); /// /// Include files /// foreach (var ifile in method.theMethod.IncludeFiles) { gc.AddIncludeFile(ifile); } /// /// We aren't re-writing this expression, so just return it. /// return result; }
/// <summary> /// MethodCallExpression visit method /// </summary> /// <param name="m">The MethodCallExpression expression to visit</param> /// <returns>The visited MethodCallExpression expression </returns> internal override Expression VisitMethodCall(MethodCallExpression m) { string methodName; if (TypeSystem.TryGetQueryOptionMethod(m.Method, out methodName)) { this.builder.Append(methodName); this.builder.Append(UriHelper.LEFTPAREN); // There is a single function, 'contains', which reorders its argument with // respect to the CLR method. Thus handling it as a special case rather than // using a more general argument reordering mechanism. if (methodName == "contains") { Debug.Assert(m.Method.Name == "Contains", "m.Method.Name == 'Contains'"); Debug.Assert(m.Object != null, "m.Object != null"); Debug.Assert(m.Arguments.Count == 1, "m.Arguments.Count == 1"); this.Visit(m.Object); this.builder.Append(UriHelper.COMMA); this.Visit(m.Arguments[0]); } else { if (m.Object != null) { this.Visit(m.Object); } if (m.Arguments.Count > 0) { if (m.Object != null) { this.builder.Append(UriHelper.COMMA); } for (int ii = 0; ii < m.Arguments.Count; ii++) { this.Visit(m.Arguments[ii]); if (ii < m.Arguments.Count - 1) { this.builder.Append(UriHelper.COMMA); } } } } this.builder.Append(UriHelper.RIGHTPAREN); } else if (m.Method.Name == "HasFlag") { Debug.Assert(m.Method.Name == "HasFlag", "m.Method.Name == 'HasFlag'"); Debug.Assert(m.Object != null, "m.Object != null"); Debug.Assert(m.Arguments.Count == 1, "m.Arguments.Count == 1"); this.Visit(m.Object); this.builder.Append(UriHelper.SPACE); this.builder.Append(UriHelper.HAS); this.builder.Append(UriHelper.SPACE); this.Visit(m.Arguments[0]); } else { SequenceMethod sequenceMethod; if (ReflectionUtil.TryIdentifySequenceMethod(m.Method, out sequenceMethod)) { if (ReflectionUtil.IsAnyAllMethod(sequenceMethod)) { // Raise the uriVersion each time we write any or all methods to the uri. WebUtil.RaiseVersion(ref this.uriVersion, Util.ODataVersion4); this.Visit(m.Arguments[0]); this.builder.Append(UriHelper.FORWARDSLASH); if (sequenceMethod == SequenceMethod.All) { this.builder.Append(XmlConstants.AllMethodName); } else { this.builder.Append(XmlConstants.AnyMethodName); } this.builder.Append(UriHelper.LEFTPAREN); if (sequenceMethod != SequenceMethod.Any) { // SequenceMethod.Any represents Enumerable.Any(), which has only source argument // AnyPredicate and All has a second parameter which is the predicate lambda. Debug.Assert(m.Arguments.Count() == 2, "m.Arguments.Count() == 2"); LambdaExpression le = (LambdaExpression)m.Arguments[1]; string rangeVariable = le.Parameters[0].Name; this.builder.Append(rangeVariable); this.builder.Append(UriHelper.COLON); this.scopeCount++; this.Visit(le.Body); this.scopeCount--; } this.builder.Append(UriHelper.RIGHTPAREN); return m; } else if (sequenceMethod == SequenceMethod.OfType && this.parent != null) { // check to see if this is an OfType filter for Any or All. // e.g. ctx.CreateQuery<Movie>("Movies").Where(m=>m.Actors.OfType<MegaStar>().Any()) // which translates to /Movies()?$filter=Actors/MegaStar/any() MethodCallExpression mce = this.parent as MethodCallExpression; if (mce != null && ReflectionUtil.TryIdentifySequenceMethod(mce.Method, out sequenceMethod) && ReflectionUtil.IsAnyAllMethod(sequenceMethod)) { Type filteredType = mce.Method.GetGenericArguments().SingleOrDefault(); if (ClientTypeUtil.TypeOrElementTypeIsEntity(filteredType)) { this.Visit(m.Arguments[0]); this.builder.Append(UriHelper.FORWARDSLASH); UriHelper.AppendTypeSegment(this.builder, filteredType, this.context, this.inPath, ref this.uriVersion); return m; } } } else if (sequenceMethod == SequenceMethod.Count && this.parent != null) { if (m.Arguments.Any() && m.Arguments[0] != null) { this.Visit(m.Arguments[0]); } this.builder.Append(UriHelper.FORWARDSLASH).Append(UriHelper.DOLLARSIGN).Append(UriHelper.COUNT); return m; } } else { if (m.Object != null) { this.Visit(m.Object); } if (m.Method.Name != "GetValue" && m.Method.Name != "GetValueAsync") { this.builder.Append(UriHelper.FORWARDSLASH); // writing functions in query options writingFunctionsInQuery = true; string declaringType = this.context.ResolveNameFromTypeInternal(m.Method.DeclaringType); if (string.IsNullOrEmpty(declaringType)) { throw new NotSupportedException(Strings.ALinq_CantTranslateExpression(m.ToString())); } int index = declaringType.LastIndexOf('.'); string fullNamespace = declaringType.Remove(index + 1); string serverMethodName = ClientTypeUtil.GetServerDefinedName(m.Method); this.builder.Append(fullNamespace + serverMethodName); this.builder.Append(UriHelper.LEFTPAREN); string[] argumentNames = m.Method.GetParameters().Select(p => p.Name).ToArray(); for (int i = 0; i < m.Arguments.Count; ++i) { this.builder.Append(argumentNames[i]); this.builder.Append(UriHelper.EQUALSSIGN); this.scopeCount++; this.Visit(m.Arguments[i]); this.scopeCount--; this.builder.Append(UriHelper.COMMA); } if (m.Arguments.Any()) { this.builder.Remove(this.builder.Length - 1, 1); } this.builder.Append(UriHelper.RIGHTPAREN); writingFunctionsInQuery = false; } return m; } this.cantTranslateExpression = true; } return m; }
/// <summary> /// Process a Contains method call which does not map one-to-one on an odata supported method. /// </summary> /// <param name="expression"> /// The expression to visit. /// </param> /// <returns> /// The visited expression. /// </returns> private void VisitContainsMethodCall(MethodCallExpression expression) { IEnumerable<Expression> arguments = GetFilterMethodArguments(expression, expression.Method.Name, expression.Method.IsGenericMethod); //First argument should be a enumerable of constants // if you would like to do a enumerable.select().where.. // you should do that outside of the query for now IEnumerable enumerable = null; Expression expr = arguments.FirstOrDefault(); if (expr != null && expr is ConstantExpression) { enumerable = ((ConstantExpression)expr).Value as IEnumerable; } Expression comparand = arguments.Skip(1).FirstOrDefault(); if (enumerable != null && comparand != null) { List<object> elements = enumerable.OfType<object>().ToList(); if(elements.Count > 0) { // create our rewritten expression tree // by tranforming the contains into a concatenation of 'or' expressions Expression orExpression = elements.Select(o => Expression.Equal(comparand, Expression.Constant(o))) .Aggregate((e1, e2) => Expression.OrElse(e1, e2)); this.Visit(orExpression); } } else { throw new NotSupportedException( string.Format( CultureInfo.InvariantCulture, Resources.FilterBuildingExpressionVisitor_UnsupportedInWhereExpression, expression != null ? expression.ToString() : null)); } }
internal override Expression VisitMethodCall(MethodCallExpression m) { if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object)) || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a))) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m)) { CheckChainedSequence(m, this.type); // allow selects for following pattern: // Orders = c.Orders.Select(o=> new NarrowOrder {...}).ToList(); return base.VisitMethodCall(m); } throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString())); }
protected override Expression VisitMethodCall(MethodCallExpression m) { string s = m.ToString(); sb.Append(s.Substring(s.IndexOf('.') + 1)); return m; }
internal override Expression VisitMethodCall(MethodCallExpression m) { if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object)) || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a))) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m)) { CheckChainedSequence(m, this.type); return base.VisitMethodCall(m); } throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString())); }
protected override Expression VisitMethodCall(MethodCallExpression e) { if (e.Method.DeclaringType == typeof(StringQueryExtensions)) return VisitStringQxMethodCall(e); if (e.Method.DeclaringType == typeof(string)) return VisitStringMethodCall(e); if (e.Method.DeclaringType == typeof(EnumerableQueryExtensions)) return VisitEnumerableQxMethodCall(e); try { var value = e.Evaluate(); var constant = Expression.Constant(value); Visit(constant); } catch (Exception ex) { throw new NotSupportedException( ExceptionMessages.LambdaParser_UnsupportedMethodCall.Inject(e.ToString()), ex); } return e; }
/// <summary> /// Process method calls which do not map one-to-one on an odata supported method. /// Currently we only support Contains. /// </summary> /// <param name="expression"> /// The expression to visit. /// </param> private void VisitCustomMethodCall(MethodCallExpression expression) { if (expression.Method.Name.Equals("Contains")) { this.VisitContainsMethodCall(expression); } else { throw new NotSupportedException( string.Format( CultureInfo.InvariantCulture, "'{0}' is not supported in a 'Where' Mobile Services query expression.", expression != null ? expression.ToString() : null)); } }
protected override Expression VisitMethodCall(MethodCallExpression m) { string s = m.ToString(); string mc = s.Substring(s.IndexOf('.') + 1); if (mc.Contains("Between")) { // TODO : add code for between parsing here string name = m.Arguments[0].ToString().Split('.')[1]; object from = GetValueForMember(m.Arguments[1]); object to = GetValueForMember(m.Arguments[2]); //var bits = qfromto(name, from, to); } else _stack.Push(mc); return m; }
private Expression GetAccumulatorArgument(MethodCallExpression node) { switch (node.Method.Name) { case "Count": case "LongCount": if (node.Arguments.Count == 1) { return Expression.Constant(1); } break; case "Average": case "Min": case "Max": case "Sum": if (node.Arguments.Count == 2) { return GetLambda(node.Arguments[1]).Body; } else if (node.Arguments.Count == 1) { return GetBodyFromSelector(node); } break; case "First": case "Last": // we have already normalized First/Last calls to only have 1 argument... if (node.Arguments.Count == 1) { return GetBodyFromSelector(node); } break; case "Select": if (node.Arguments.Count == 2) { return GetLambda(node.Arguments[1]).Body; } break; case "Distinct": case "ToArray": case "ToList": if (node.Arguments.Count == 1) { return GetBodyFromSelector(node); } break; } var message = string.Format("Unsupported version of accumulator method {0} in the expression tree: {1}.", node.Method.Name, node.ToString()); throw new NotSupportedException(message); }
internal override Expression VisitMethodCall(MethodCallExpression m) { if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m)) { ProjectionAnalyzer.CheckChainedSequence(m, this.type); return base.VisitMethodCall(m); } if ((m.Object != null ? CommonUtil.IsClientType(m.Object.Type) : false) || m.Arguments.Any(a => CommonUtil.IsClientType(a.Type))) { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjection, this.type, m.ToString())); } return base.VisitMethodCall(m); }
private BsonValue TranslateMethodCall(MethodCallExpression node) { BsonValue result; if (node.Object == null) { if (node.Method.DeclaringType == typeof(string) && TryTranslateStaticStringMethodCall(node, out result)) { return result; } if (node.Method.DeclaringType == typeof(Math) && TryTranslateStaticMathMethodCall(node, out result)) { return result; } } else { if (node.Object.Type == typeof(string) && TryTranslateStringMethodCall(node, out result)) { return result; } if (node.Object.Type.IsGenericType && node.Object.Type.GetGenericTypeDefinition() == typeof(HashSet<>) && TryTranslateHashSetMethodCall(node, out result)) { return result; } if (node.Method.Name == "CompareTo" && (node.Object.Type.ImplementsInterface(typeof(IComparable<>)) || node.Object.Type.ImplementsInterface(typeof(IComparable)))) { return new BsonDocument("$cmp", new BsonArray(new[] { TranslateValue(node.Object), TranslateValue(node.Arguments[0]) })); } if (node.Method.Name == "Equals" && node.Arguments.Count == 1) { return new BsonDocument("$eq", new BsonArray(new[] { TranslateValue(node.Object), TranslateValue(node.Arguments[0]) })); } } var message = string.Format("{0} of type {1} is not supported in the expression tree {2}.", node.Method.Name, node.Method.DeclaringType, node.ToString()); throw new NotSupportedException(message); }
internal override Expression VisitMethodCall(MethodCallExpression m) { // We throw NotSupportedException when IsDisallowedExceptionForMethodCall() is true // or we have a method call on a non-entity type, for example c.MyCollectionComplexProperty.Select(...) if ((m.Object != null && (IsDisallowedExpressionForMethodCall(m.Object, this.context.Model) || !ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type))) || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a, this.context.Model)) || (m.Object == null && !ClientTypeUtil.TypeOrElementTypeIsEntity(m.Arguments[0].Type))) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m)) { CheckChainedSequence(m, this.type); // allow selects for following pattern: // Orders = c.Orders.Select(o=> new NarrowOrder {...}).ToList(); return base.VisitMethodCall(m); } throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString())); }
/// <summary> /// Checks whether the specified <see cref="MethodCallExpression"/> refers /// to a Select method call that works on the results of another Select call /// </summary> /// <param name="call">Method call expression to check.</param> /// <param name="type">Type of the projection</param> internal static void CheckChainedSequence(MethodCallExpression call, Type type) { if (ReflectionUtil.IsSequenceMethod(call.Method, SequenceMethod.Select)) { // Chained Selects are not allowed // c.Orders.Select(...).Select(...) MethodCallExpression insideCall = ResourceBinder.StripTo<MethodCallExpression>(call.Arguments[0]); if (insideCall != null && ReflectionUtil.IsSequenceMethod(insideCall.Method, SequenceMethod.Select)) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(type, call.ToString())); } } }
internal override Expression VisitMethodCall(MethodCallExpression m) { if (((m.Object != null) && ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(m.Object, this.context.MaxProtocolVersion)) || m.Arguments.Any<Expression>(a => ProjectionAnalyzer.IsDisallowedExpressionForMethodCall(a, this.context.MaxProtocolVersion))) { throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } ProjectionAnalyzer.CheckChainedSequence(m, this.type); if (!ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m) && (((m.Object != null) ? ClientTypeUtil.TypeOrElementTypeIsEntity(m.Object.Type) : false) || m.Arguments.Any<Expression>(a => ClientTypeUtil.TypeOrElementTypeIsEntity(a.Type)))) { throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } return base.VisitMethodCall(m); }
internal override Expression VisitMethodCall(MethodCallExpression m) { if ((m.Object != null && IsDisallowedExpressionForMethodCall(m.Object)) || m.Arguments.Any(a => IsDisallowedExpressionForMethodCall(a))) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } if (ProjectionAnalyzer.IsMethodCallAllowedEntitySequence(m)) { CheckChainedSequence(m, this.type); // allow IEnum.Select and IEnum.ToList even if entity type. return base.VisitMethodCall(m); } if ((m.Object != null ? ClientType.CheckElementTypeIsEntity(m.Object.Type) : false) || m.Arguments.Any(a => ClientType.CheckElementTypeIsEntity(a.Type))) { throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString())); } return base.VisitMethodCall(m); }
internal static void CheckChainedSequence(MethodCallExpression call, Type type) { if (ReflectionUtil.IsSequenceSelectMethod(call.Method)) { MethodCallExpression expression = ResourceBinder.StripTo<MethodCallExpression>(call.Arguments[0]); if ((expression != null) && ReflectionUtil.IsSequenceSelectMethod(expression.Method)) { throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(type, call.ToString())); } } }
/// <summary> /// Process method calls which do not map one-to-one on an odata supported method. /// Currently we only support Contains. /// </summary> /// <param name="expression"> /// The expression to visit. /// </param> private void VisitCustomMethodCall(MethodCallExpression expression) { if (expression.Method.Name.Equals("Contains")) { this.VisitContainsMethodCall(expression); } else { throw new NotSupportedException( string.Format( CultureInfo.InvariantCulture, Resources.FilterBuildingExpressionVisitor_UnsupportedInWhereExpression, expression != null ? expression.ToString() : null)); } }
/// <summary> /// 访问指定的方法 /// </summary> /// <param name="theEntityType">实体的类型</param> /// <param name="m">访问方法调用相关的表达式</param> /// <param name="tableAlias">表的别名</param> /// <param name="colConditionParts">存储条件节点的栈</param> /// <param name="colParameterNames">存储参数名称的列表</param> /// <param name="colDbTypes">存储数据库字段类型的列表</param> /// <param name="colArguments">存储条件值的列表</param> public static void Visit(Type theEntityType, MethodCallExpression m, string tableAlias, Stack<string> colConditionParts, List<string> colParameterNames, List<DbType> colDbTypes, List<object> colArguments) { string methodName = m.Method.Name; if (m.Object is MemberExpression) { string condition = null; //string memberName = GetMemberName(m.Object as MemberExpression, out theDbType); string memberName = EntityMappingTool.GetDbColumnName(theEntityType, ((MemberExpression) m.Object).Member.Name); DbType theDbType = EntityMappingTool.GetDbColumnType(theEntityType, ((MemberExpression) m.Object).Member.Name); string parameterName = GetParameterName(colParameterNames, memberName, tableAlias); switch (methodName) { case "Contains": condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add("%" + GetArgumentValue(m.Arguments[0] as ConstantExpression) + "%"); break; case "StartsWith": condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add(GetArgumentValue(m.Arguments[0] as ConstantExpression) + "%"); break; case "EndsWith": condition = string.Format("({0}.[{1}] like {2})", tableAlias, memberName, parameterName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add("%" + GetArgumentValue(m.Arguments[0] as ConstantExpression)); break; default: throw new EntitySqlException("暂不支持{" + m.ToString() + "}的调用!"); } } else if (m.Object is ConstantExpression) { string condition = null; string memberName = EntityMappingTool.GetDbColumnName(theEntityType, ((MemberExpression) m.Arguments[0]).Member.Name); DbType theDbType = EntityMappingTool.GetDbColumnType(theEntityType, ((MemberExpression) m.Arguments[0]).Member.Name); string parameterName = GetParameterName(colParameterNames, memberName, tableAlias); switch (methodName) { case "Contains": condition = string.Format("(CHARINDEX({0},{1}.[{2}])>0)", parameterName, tableAlias, memberName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add(GetArgumentValue(m.Object as ConstantExpression)); break; case "StartsWith": condition = string.Format("(CHARINDEX({0},{1}.[{2}])=1)", parameterName, tableAlias, memberName); colConditionParts.Push(condition); colParameterNames.Add(parameterName); colDbTypes.Add(theDbType); colArguments.Add(GetArgumentValue(m.Object as ConstantExpression)); break; default: throw new EntitySqlException("暂不支持{" + m.ToString() + "}的调用!"); } } else { throw new EntitySqlException("暂不支持{" + m.ToString() + "}的调用!"); } }
private string TranslateMethodCall(MethodCallExpression node) { var methodName = node.Method.Name; MemberExpression leftExpression = null; var arguments = new List<LambdaExpression>(); if (node.Method.DeclaringType == typeof(string)) { string arg = Translate(node.Object); object[] stringArguments = node.Arguments.Select(UnQuote).OfType<ConstantExpression>().Select(exp => exp.Value).ToArray(); switch (methodName) { case "StartsWith": return string.Format("({0} like {1})", arg, CreateParameter(stringArguments[0] + "%")); case "EndsWith": return string.Format("({0} like {1})", arg, CreateParameter("%" + stringArguments[0])); case "Contains": return string.Format("({0} like {1})", arg, CreateParameter("%" + stringArguments[0] + "%")); case "Trim": return string.Format(_sqlDialect.SqlFunction(SqlDialect.Function.Trim), stringArguments[0]); } throw new SqlExpressionTranslatorException(node.ToString()); } if (node.Method.DeclaringType.IsConstructedGenericType && node.Method.DeclaringType.GetGenericTypeDefinition() == typeof(IDataSet<>)) { leftExpression = node.Object as MemberExpression; arguments.AddRange(node.Arguments.Select(UnQuote).OfType<LambdaExpression>()); } if (node.Method.DeclaringType == typeof(Enumerable) && node.Arguments.Count > 0) { leftExpression = node.Arguments[0] as MemberExpression; arguments.AddRange(node.Arguments.Skip(1).Select(UnQuote).OfType<LambdaExpression>()); } if (leftExpression != null) { switch (methodName) { case "Any": case "Count": case "All": return TranslateOneToMany( methodName, leftExpression, null, arguments.Count > 0 ? arguments[0] : null ); case "Sum": case "Avg": return TranslateOneToMany( methodName, leftExpression, arguments[0], null ); } } throw new SqlExpressionTranslatorException(node.ToString()); }
internal static void CheckChainedSequence(MethodCallExpression call, Type type) { if (ReflectionUtil.IsSequenceMethod(call.Method, SequenceMethod.Select)) { MethodCallExpression insideCall = ResourceBinder.StripTo<MethodCallExpression>(call.Arguments[0]); if (insideCall != null && ReflectionUtil.IsSequenceMethod(insideCall.Method, SequenceMethod.Select)) { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjection, type, call.ToString())); } } }
protected override Expression VisitOtherMethodCall(MethodCallExpression expression) { throw new NotSupportedException(String.Format("Method Call to {0} is not supported.", expression.ToString())); }
private Expression BuildFromMethodCall(MethodCallExpression node) { Expression source; IEnumerable<Expression> arguments; if (node.Object != null) { source = node.Object; arguments = node.Arguments; } else { // assuming an extension method here... source = node.Arguments[0]; arguments = node.Arguments.Skip(1); } var projection = BindProjection(source); var result = _methodCallBinder.Bind(projection, _context, node, arguments); if (result == null) { var message = string.Format("The method {0} is not supported in the expression tree: {1}.", node.Method.Name, node.ToString()); throw new NotSupportedException(message); } return result; }