protected override Expression VisitMethodCall(MethodCallExpression node) { Expression rewrite = null; if (TryUncheckedCast(node,ref rewrite)) return rewrite; return base.VisitMethodCall(node); }
private static string GetTypeOfNthParamOfMethod(int ParamIndex, MethodCallExpression MethodCallExpression) { MethodReferenceExpression OuterMethodReference = (MethodCallExpression.Nodes[0] as DevExpress.CodeRush.StructuralParser.MethodReferenceExpression); var Declaration1 = OuterMethodReference.GetDeclaration() as Method; // Previous line will return null if any parameter isn't explicitly calculable. if (Declaration1 == null) return ""; // Suggest void. Wrong, but best available option. var Param = Declaration1.Parameters[ParamIndex] as Param; return Param.GetTypeName(); }
/// <summary> /// Given a MethodCallExpression, copy the expression, replacing the source with the source provided /// </summary> /// <param name="source"></param> /// <param name="mce"></param> /// <returns></returns> private static System.Linq.Expressions.MethodCallExpression ResourceQueryOperatorCall(System.Linq.Expressions.Expression source, MethodCallExpression mce) { List <System.Linq.Expressions.Expression> exprs = new List <System.Linq.Expressions.Expression>(); exprs.Add(source); exprs.AddRange(mce.Arguments.Skip(1)); return(System.Linq.Expressions.Expression.Call(mce.Method, exprs.ToArray())); }
protected override Expression VisitMethodCall(MethodCallExpression m) { Accumulate(m.Method); return base.VisitMethodCall(m); }
///////////////////////////////////////////////////////////////////////////// public override string DumpMethodCallExpression( MethodCallExpression exp ) { return string.Format( ".{0}({1})", exp.MethodName, Arguments(exp.Arguments) ); }
/// <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, 'substringof', 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 == "substringof") { 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.Arguments[0]); this.builder.Append(UriHelper.COMMA); this.Visit(m.Object); } 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 { 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.DataServiceVersion3); 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); } } } } this.cantTranslateExpression = true; } return(m); }
private static void AssertCallIsOptimized(MethodCallExpression expr, Expression instance, MethodInfo method, IReadOnlyList<Expression> args) { int n = method.GetParameters().Length; MethodCallExpression updatedArgs = UpdateArgs(expr); MethodCallExpression visitedArgs = VisitArgs(expr); var updatedObj = default(MethodCallExpression); var visitedObj = default(MethodCallExpression); MethodCallExpression[] nodes; if (instance == null) { nodes = new[] { expr, updatedArgs, visitedArgs }; } else { updatedObj = UpdateObj(expr); visitedObj = VisitObj(expr); nodes = new[] { expr, updatedArgs, visitedArgs, updatedObj, visitedObj }; } foreach (var node in nodes) { if (node != visitedObj && node != updatedObj) { Assert.Same(instance, node.Object); } Assert.Same(method, node.Method); if (method.IsStatic) { AssertStaticMethodCall(n, node); } else { AssertInstanceMethodCall(n, node); } var argProvider = node as IArgumentProvider; Assert.NotNull(argProvider); Assert.Equal(n, argProvider.ArgumentCount); Assert.Throws<ArgumentOutOfRangeException>(() => argProvider.GetArgument(-1)); Assert.Throws<ArgumentOutOfRangeException>(() => argProvider.GetArgument(n)); if (node != visitedArgs) // our visitor clones argument nodes { for (var i = 0; i < n; i++) { Assert.Same(args[i], argProvider.GetArgument(i)); Assert.Same(args[i], node.Arguments[i]); } } } }
// MethodCallExpression protected internal virtual bool Walk(MethodCallExpression node) { return true; }
protected virtual bool CompareMethodCall(MethodCallExpression a, MethodCallExpression b) { return a.Method == b.Method && this.Compare(a.Object, b.Object) && this.CompareExpressionList(a.Arguments, b.Arguments); }
/// <summary> /// Returns the operator to emit (e.g. LIKE/ILIKE). /// </summary> /// <param name="expression"></param> /// <returns></returns> protected virtual string GetOperator(MethodCallExpression expression) { return(IsCaseInsensitiveComparison(expression) ? "ILIKE" : "LIKE"); }
public static ITranslation GetSubjectTranslation(MethodCallExpression methodCall, ITranslationContext context) { return(context.GetTranslationFor(methodCall.GetSubject()) ?? context.GetTranslationFor(methodCall.Method.DeclaringType)); }
public static void Show() { { Func <int, int, int> func = (m, n) => m * n + 2; Expression <Func <int, int, int> > exp = (m, n) => m * n + 2;//lambda表达式声明表达式目录树 //Expression<Func<int, int, int>> exp1 = (m, n) => // { // return m * n + 2; // }; //表达式目录树:语法树,或者说是一种数据结构 int iResult1 = func.Invoke(12, 23); int iResult2 = exp.Compile().Invoke(12, 23); } { //自己拼装表达式目录树 ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "m"); //m ParameterExpression parameterExpression2 = Expression.Parameter(typeof(int), "n"); //n BinaryExpression binaryExpression = Expression.Multiply(parameterExpression, parameterExpression2); //m*n ConstantExpression constantExpression = Expression.Constant(2, typeof(int)); //2 BinaryExpression binaryExpressionAdd = Expression.Add(binaryExpression, constantExpression); //M*N+2 Expression <Func <int, int, int> > exp = Expression.Lambda <Func <int, int, int> >(binaryExpressionAdd, new ParameterExpression[] { parameterExpression, parameterExpression2 }); int iResult2 = exp.Compile().Invoke(12, 23); } { ParameterExpression paraLeft = Expression.Parameter(typeof(int), "a"); //左边 ParameterExpression paraRight = Expression.Parameter(typeof(int), "b"); //右边 BinaryExpression binaryLeft = Expression.Multiply(paraLeft, paraRight); //a*b ConstantExpression conRight = Expression.Constant(2, typeof(int)); //右边常量 BinaryExpression binaryBody = Expression.Add(binaryLeft, conRight); //a*b+2 //只能执行表示Lambda表达式的表达式目录树,即LambdaExpression或者Expression<TDelegate>类型。如果表达式目录树不是表示Lambda表达式,需要调用Lambda方法创建一个新的表达式 Expression <Func <int, int, int> > lambda = Expression.Lambda <Func <int, int, int> >(binaryBody, paraLeft, paraRight); Func <int, int, int> func = lambda.Compile();//Expression Compile成委托 int result = func(3, 4); } { //常量 ConstantExpression conLeft = Expression.Constant(345); ConstantExpression conRight = Expression.Constant(456); BinaryExpression binary = Expression.Add(conLeft, conRight); //添加方法的 Expression <Action> actExpression = Expression.Lambda <Action>(binary, null); actExpression.Compile()(); //()=>345+456 } { string sql = "SELECT * FROM uSER WHERE 1=1"; if (true) { sql += " and "; } if (true) { sql += " and "; } IQueryable <int> list = null; //if (true) list = list.Where(i => i > 5); //if (true) list = list.Where(i => i > 5); if (true) { Expression <Func <int, bool> > exp1 = x => x > 1; } if (true) { Expression <Func <int, bool> > exp2 = x => x > 2; } Expression <Func <int, bool> > exp3 = x => x > 1 && x > 2; //list.Where() //拼装表达式目录树,交给下端用 //Expression<Func<People, bool>> lambda = x => x.Age > 5; ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x"); //Expression property = Expression.Property(parameterExpression, typeof(People).GetProperty("Age")); Expression property = Expression.Field(parameterExpression, typeof(People).GetField("Id")); ConstantExpression constantExpression = Expression.Constant(5, typeof(int)); BinaryExpression binary = Expression.GreaterThan(property, constantExpression);//添加方法的 Expression <Func <People, bool> > lambda = Expression.Lambda <Func <People, bool> >(binary, new ParameterExpression[] { parameterExpression }); bool bResult = lambda.Compile()(new People() { Id = 11, Name = "打兔子的猎人", Age = 28 }); } { //Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5"); ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x"); Expression field = Expression.Field(parameterExpression, typeof(People).GetField("Id")); MethodCallExpression toString = Expression.Call(field, typeof(People).GetMethod("ToString"), new Expression[0]); ConstantExpression constantExpression = Expression.Constant("5", typeof(string)); MethodCallExpression equals = Expression.Call(toString, typeof(People).GetMethod("Equals"), new Expression[] { constantExpression }); Expression <Func <People, bool> > lambda = Expression.Lambda <Func <People, bool> >(equals, new ParameterExpression[] { parameterExpression }); bool bResult = lambda.Compile()(new People() { Id = 11, Name = "打兔子的猎人", Age = 28 }); } { People people = new People() { Id = 11, Name = "打兔子的猎人", Age = 28 }; PeopleCopy peopleCopy = new PeopleCopy() { Id = people.Id, Name = people.Name, Age = people.Age }; PeopleCopy peopleCopy1 = Trans <People, PeopleCopy>(people); //Expression<Func<People, PeopleCopy>> lambda = p => // new PeopleCopy() // { // Id = p.Id, // Name = p.Name, // Age = p.Age // }; //lambda.Compile()(people); ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "p"); List <MemberBinding> memberBindingList = new List <MemberBinding>(); foreach (var item in typeof(PeopleCopy).GetProperties()) { MemberExpression property = Expression.Property(parameterExpression, typeof(People).GetProperty(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } foreach (var item in typeof(PeopleCopy).GetFields()) { MemberExpression property = Expression.Field(parameterExpression, typeof(People).GetField(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(PeopleCopy)), memberBindingList.ToArray()); Expression <Func <People, PeopleCopy> > lambda = Expression.Lambda <Func <People, PeopleCopy> >(memberInitExpression, new ParameterExpression[] { parameterExpression }); Func <People, PeopleCopy> func = lambda.Compile();//拼装是一次性的 TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(people); TransExp <People, PeopleCopy>(new People() { Id = 12, Name = "小雨天", Age = 26 }); } #region 表达式链接 { Expression <Func <People, bool> > lambda1 = x => x.Age > 5; Expression <Func <People, bool> > lambda2 = x => x.Id > 5; Expression <Func <People, bool> > lambda3 = lambda1.And(lambda2); Expression <Func <People, bool> > lambda4 = lambda1.Or(lambda2); Expression <Func <People, bool> > lambda5 = lambda1.Not(); Do1(lambda3); Do1(lambda4); Do1(lambda5); } #endregion }
private static bool IsStringConcatCall(MethodCallExpression methodCall) { return(methodCall.Method.IsStatic && (methodCall.Method.DeclaringType == typeof(string)) && (methodCall.Method.Name == "Concat")); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequenceExpr = methodCall.Arguments[0]; var wrapSequence = false; LambdaExpression?groupingKey = null; var groupingKind = GroupingType.Default; if (sequenceExpr.NodeType == ExpressionType.Call) { var call = (MethodCallExpression)methodCall.Arguments[0]; if (call.IsQueryable("Select")) { var selectParam = (LambdaExpression)call.Arguments[1].Unwrap(); var type = selectParam.Body.Type; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>)) { wrapSequence = true; var selectParamBody = selectParam.Body.Unwrap(); MethodCallExpression?groupingMethod = null; if (selectParamBody is MemberInitExpression mi) { var assignment = mi.Bindings.OfType <MemberAssignment>().FirstOrDefault(m => m.Member.Name == "Key"); if (assignment?.Expression.NodeType == ExpressionType.Call) { var mc = (MethodCallExpression)assignment.Expression; if (mc.IsSameGenericMethod(GroupingSetMethods)) { groupingMethod = mc; groupingKey = (LambdaExpression)mc.Arguments[0].Unwrap(); if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Rollup)) { groupingKind = GroupingType.Rollup; } else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Cube)) { groupingKind = GroupingType.Cube; } else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.GroupingSets)) { groupingKind = GroupingType.GroupBySets; } else { throw new InvalidOperationException(); } } } } if (groupingMethod != null && groupingKey != null) { sequenceExpr = sequenceExpr.Replace(groupingMethod, groupingKey.Body.Unwrap()); } } } } var sequence = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr)); var keySequence = sequence; var groupingType = methodCall.Type.GetGenericArguments()[0]; var keySelector = (LambdaExpression)methodCall.Arguments[1].Unwrap() !; var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap() !; if (wrapSequence) { sequence = new SubQueryContext(sequence); } sequence = new SubQueryContext(sequence); var key = new KeyContext(buildInfo.Parent, keySelector, sequence); if (groupingKind != GroupingType.GroupBySets) { var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key, null); var allowed = groupSql.Where(s => !QueryHelper.IsConstantFast(s.Sql)); foreach (var sql in allowed) { sequence.SelectQuery.GroupBy.Expr(sql.Sql); } } else { var goupingSetBody = groupingKey !.Body; var groupingSets = EnumGroupingSets(goupingSetBody).ToArray(); if (groupingSets.Length == 0) { throw new LinqException($"Invalid grouping sets expression '{goupingSetBody}'."); } foreach (var groupingSet in groupingSets) { var groupSql = builder.ConvertExpressions(keySequence, groupingSet, ConvertFlags.Key, null); sequence.SelectQuery.GroupBy.Items.Add( new SqlGroupingSet(groupSql.Select(s => keySequence.SelectQuery.Select.AddColumn(s.Sql)))); } } sequence.SelectQuery.GroupBy.GroupingType = groupingKind; var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/); var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element, builder.IsGroupingGuardDisabled); Debug.WriteLine("BuildMethodCall GroupBy:\n" + groupBy.SelectQuery); return(groupBy); }
/// <summary> /// Returns a locator for the member being queried upon /// </summary> /// <param name="mapping"></param> /// <param name="expression"></param> /// <returns></returns> protected string GetLocator(IFieldMapping mapping, MethodCallExpression expression) { var memberExpression = determineStringField(expression); return(mapping.FieldFor(memberExpression).RawLocator); }
protected MethodCallExpression UpdateMethodCall(MethodCallExpression m, Expression obj, MethodInfo method, IEnumerable<Expression> args) { if (obj != m.Object || method != m.Method || args != m.Arguments) { return Expression.Call(obj, method, args); } return m; }
///////////////////////////////////////////////////////////////////////////// protected Expression MethodCall( bool isRootNode, string methodName, bool validToken, IInput input ) { // ****** Expression expression = null; IArgumentsProcessor ap = new ArgumentsProcessor( scanner, recognizer ); NmpStringList strArgs = scanner.ArgScanner( input, RecognizedCharType.CloseParenChar ); // ****** if( ! validToken ) { // // IndexResult // return new UnnamedMethodCallExpression( ap, strArgs ); } else { if( isRootNode ) { expression = new UnnamedMethodCallExpression( methodName, ap, strArgs ); } else { expression = new MethodCallExpression( methodName, ap, strArgs ); } } // ****** return expression; }
protected override Expression VisitMethodCall(MethodCallExpression node) { return(Visiting((expr) => base.VisitMethodCall(expr as MethodCallExpression), node)); }
public abstract string DumpMethodCallExpression( MethodCallExpression exp );
internal static IProjection ProcessDoubleAbs(MethodCallExpression methodCallExpression) { IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection(); return(Projections.SqlFunction("abs", NHibernateUtil.Double, property)); }
internal static IProjection ProcessBitLength(MethodCallExpression methodCallExpression) { IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection(); return(Projections.SqlFunction("bit_length", NHibernateUtil.String, property)); }
public MethodCallExpressionProxy(MethodCallExpression node) { _node = node; }
private bool CompareMethodCall(MethodCallExpression a, MethodCallExpression b) => Equals(a.Method, b.Method) && Compare(a.Object, b.Object) && CompareExpressionList(a.Arguments, b.Arguments);
private static MethodCallExpression UpdateObj(MethodCallExpression node) { // Tests the call of Update to Expression.Call factories. MethodCallExpression res = node.Update(new VisitorObj().Visit(node.Object), node.Arguments); Assert.NotSame(node, res); return res; }
public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) { Func <Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc); if (exp.Object == null) { switch (exp.Method.Name) { case "IsNullOrEmpty": var arg1 = getExp(exp.Arguments[0]); return($"({arg1} is null or {arg1} = '')"); case "IsNullOrWhiteSpace": var arg2 = getExp(exp.Arguments[0]); return($"({arg2} is null or {arg2} = '' or ltrim({arg2}) = '')"); case "Concat": return(_common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null)); case "Format": if (exp.Arguments[0].NodeType != ExpressionType.Constant) { throw new Exception(CoreStrings.Not_Implemented_Expression_ParameterUseConstant(exp, exp.Arguments[0])); } var expArgsHack = exp.Arguments.Count == 2 && exp.Arguments[1].NodeType == ExpressionType.NewArrayInit ? (exp.Arguments[1] as NewArrayExpression).Expressions : exp.Arguments.Where((a, z) => z > 0); //3个 {} 时,Arguments 解析出来是分开的 //4个 {} 时,Arguments[1] 只能解析这个出来,然后里面是 NewArray [] var expArgs = expArgsHack.Select(a => $"'||{_common.IsNull(ExpressionLambdaToSql(a, tsc), "''")}||'").ToArray(); return(string.Format(ExpressionLambdaToSql(exp.Arguments[0], tsc), expArgs)); case "Join": //未通用测试 #405 if (exp.IsStringJoin(out var tolistObjectExp, out var toListMethod, out var toListArgs1)) { var newToListArgs0 = Expression.Call(tolistObjectExp, toListMethod, Expression.Lambda( Expression.Call( typeof(SqlExtExtensions).GetMethod("StringJoinOracleGroupConcat"), Expression.Convert(toListArgs1.Body, typeof(object)), Expression.Convert(exp.Arguments[0], typeof(object))), toListArgs1.Parameters)); var newToListSql = getExp(newToListArgs0); return(newToListSql); } break; } } else { var left = getExp(exp.Object); switch (exp.Method.Name) { case "StartsWith": case "EndsWith": case "Contains": var args0Value = getExp(exp.Arguments[0]); if (args0Value == "NULL") { return($"({left}) IS NULL"); } var likeOpt = "LIKE"; if (exp.Arguments.Count > 1) { if (exp.Arguments[1].Type == typeof(bool) || exp.Arguments[1].Type == typeof(StringComparison)) { likeOpt = "ILIKE"; } } if (exp.Method.Name == "StartsWith") { return($"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::text || '%')")}"); } if (exp.Method.Name == "EndsWith") { return($"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::text)")}"); } if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) { return($"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}"); } return($"({left}) {likeOpt} ('%' || ({args0Value})::text || '%')");
private void AddressOf(MethodCallExpression node, Type type) { // An array index of a multi-dimensional array is represented by a call to Array.Get, // rather than having its own array-access node. This means that when we are trying to // get the address of a member of a multi-dimensional array, we'll be trying to // get the address of a Get method, and it will fail to do so. Instead, detect // this situation and replace it with a call to the Address method. if (!node.Method.IsStatic && node.Object.Type.IsArray && node.Method == node.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)) { MethodInfo mi = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance); EmitMethodCall(node.Object, mi, node); } else { EmitExpressionAddress(node, type); } }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsQueryable("Skip", "Take")); }
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.Method.DeclaringType == typeof(Queryable) && methodCallExpression.Method.IsGenericMethod) { var genericMethod = methodCallExpression.Method.GetGenericMethodDefinition(); if (genericMethod == QueryableMethods.SelectManyWithCollectionSelector) { // SelectMany var selectManySource = methodCallExpression.Arguments[0]; if (selectManySource is MethodCallExpression groupJoinMethod && groupJoinMethod.Method.IsGenericMethod && groupJoinMethod.Method.GetGenericMethodDefinition() == QueryableMethods.GroupJoin) { // GroupJoin var outer = Visit(groupJoinMethod.Arguments[0]); var inner = Visit(groupJoinMethod.Arguments[1]); var outerKeySelector = groupJoinMethod.Arguments[2].UnwrapLambdaFromQuote(); var innerKeySelector = groupJoinMethod.Arguments[3].UnwrapLambdaFromQuote(); var groupJoinResultSelector = groupJoinMethod.Arguments[4].UnwrapLambdaFromQuote(); var selectManyCollectionSelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); var selectManyResultSelector = methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(); var collectionSelectorBody = selectManyCollectionSelector.Body; var defaultIfEmpty = false; if (collectionSelectorBody is MethodCallExpression collectionEndingMethod && collectionEndingMethod.Method.IsGenericMethod && collectionEndingMethod.Method.GetGenericMethodDefinition() == QueryableMethods.DefaultIfEmptyWithoutArgument) { defaultIfEmpty = true; collectionSelectorBody = collectionEndingMethod.Arguments[0]; } collectionSelectorBody = ReplacingExpressionVisitor.Replace( selectManyCollectionSelector.Parameters[0], groupJoinResultSelector.Body, collectionSelectorBody); var correlatedCollectionSelector = _selectManyVerifyingExpressionVisitor .VerifyCollectionSelector( collectionSelectorBody, groupJoinResultSelector.Parameters[1]); if (correlatedCollectionSelector) { var outerParameter = outerKeySelector.Parameters[0]; var innerParameter = innerKeySelector.Parameters[0]; var correlationPredicate = Expression.Equal( outerKeySelector.Body, innerKeySelector.Body); inner = Expression.Call( QueryableMethods.Where.MakeGenericMethod(inner.Type.TryGetSequenceType()), inner, Expression.Quote(Expression.Lambda(correlationPredicate, innerParameter))); inner = ReplacingExpressionVisitor.Replace( groupJoinResultSelector.Parameters[1], inner, collectionSelectorBody); inner = Expression.Quote(Expression.Lambda(inner, outerParameter)); } else { inner = _enumerableToQueryableReMappingExpressionVisitor.Visit( ReplacingExpressionVisitor.Replace( groupJoinResultSelector.Parameters[1], inner, collectionSelectorBody)); if (inner is MethodCallExpression innerMethodCall && innerMethodCall.Method.IsGenericMethod && innerMethodCall.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable && innerMethodCall.Type == innerMethodCall.Arguments[0].Type) { // Remove redundant AsQueryable. // It is fine to leave it in the tree since it is no-op inner = innerMethodCall.Arguments[0]; } } var resultSelectorBody = ReplacingExpressionVisitor.Replace( selectManyResultSelector.Parameters[0], groupJoinResultSelector.Body, selectManyResultSelector.Body); var resultSelector = Expression.Lambda( resultSelectorBody, groupJoinResultSelector.Parameters[0], selectManyResultSelector.Parameters[1]); if (correlatedCollectionSelector) { // select many case } else { // join case if (defaultIfEmpty) { // left join return(Expression.Call( QueryableExtensions.LeftJoinMethodInfo.MakeGenericMethod( outer.Type.TryGetSequenceType(), inner.Type.TryGetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, inner, outerKeySelector, innerKeySelector, resultSelector)); } // inner join return(Expression.Call( QueryableMethods.Join.MakeGenericMethod( outer.Type.TryGetSequenceType(), inner.Type.TryGetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, inner, outerKeySelector, innerKeySelector, resultSelector)); } } } else if (genericMethod == QueryableMethods.SelectManyWithoutCollectionSelector) { // SelectMany var selectManySource = methodCallExpression.Arguments[0]; if (selectManySource is MethodCallExpression groupJoinMethod && groupJoinMethod.Method.IsGenericMethod && groupJoinMethod.Method.GetGenericMethodDefinition() == QueryableMethods.GroupJoin) { // GroupJoin var outer = Visit(groupJoinMethod.Arguments[0]); var inner = Visit(groupJoinMethod.Arguments[1]); var outerKeySelector = groupJoinMethod.Arguments[2].UnwrapLambdaFromQuote(); var innerKeySelector = groupJoinMethod.Arguments[3].UnwrapLambdaFromQuote(); var groupJoinResultSelector = groupJoinMethod.Arguments[4].UnwrapLambdaFromQuote(); var selectManyResultSelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); var groupJoinResultSelectorBody = groupJoinResultSelector.Body; var defaultIfEmpty = false; if (groupJoinResultSelectorBody is MethodCallExpression collectionEndingMethod && collectionEndingMethod.Method.IsGenericMethod && collectionEndingMethod.Method.GetGenericMethodDefinition() == QueryableMethods.DefaultIfEmptyWithoutArgument) { defaultIfEmpty = true; groupJoinResultSelectorBody = collectionEndingMethod.Arguments[0]; } var correlatedCollectionSelector = _selectManyVerifyingExpressionVisitor .VerifyCollectionSelector( groupJoinResultSelectorBody, groupJoinResultSelector.Parameters[1]); if (!correlatedCollectionSelector) { inner = ReplacingExpressionVisitor.Replace( groupJoinResultSelector.Parameters[1], inner, groupJoinResultSelectorBody); inner = ReplacingExpressionVisitor.Replace( selectManyResultSelector.Parameters[0], inner, selectManyResultSelector.Body); inner = _enumerableToQueryableReMappingExpressionVisitor.Visit(inner); var resultSelector = Expression.Lambda( innerKeySelector.Parameters[0], groupJoinResultSelector.Parameters[0], innerKeySelector.Parameters[0]); // join case if (defaultIfEmpty) { // left join return(Expression.Call( QueryableExtensions.LeftJoinMethodInfo.MakeGenericMethod( outer.Type.TryGetSequenceType(), inner.Type.TryGetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, inner, outerKeySelector, innerKeySelector, resultSelector)); } // inner join return(Expression.Call( QueryableMethods.Join.MakeGenericMethod( outer.Type.TryGetSequenceType(), inner.Type.TryGetSequenceType(), outerKeySelector.ReturnType, resultSelector.ReturnType), outer, inner, outerKeySelector, innerKeySelector, resultSelector)); } } } } return(base.VisitMethodCall(methodCallExpression)); }
protected override Expression VisitMethodCall(MethodCallExpression m) { if (m.Method.DeclaringType == typeof(string)) { switch (m.Method.Name) { case "StartsWith": this.Write("("); this.Visit(m.Object); this.Write(" LIKE " + parameterString); this.Write(_Connector + "'%')"); SetParameter(m); return(m); case "EndsWith": this.Write("("); this.Visit(m.Object); this.Write(" LIKE '%'" + _Connector + parameterString); this.Write(")"); SetParameter(m); return(m); case "Contains": this.Write("("); this.Visit(m.Object); this.Write(" LIKE '%'" + _Connector + parameterString); this.Write(_Connector + "'%')"); SetParameter(m); return(m); case "Concat": IList <Expression> args = m.Arguments; if (args.Count == 1 && args[0].NodeType == ExpressionType.NewArrayInit) { args = ((NewArrayExpression)args[0]).Expressions; } for (int i = 0, n = args.Count; i < n; i++) { if (i > 0) { this.Write(_Connector); } this.Visit(args[i]); } return(m); case "IsNullOrEmpty": this.Write("("); this.Visit(m.Object); this.Write(" IS NULL OR "); this.Visit(m.Arguments[0]); this.Write(" = '')"); //AddParameter(new DBParameter //{ // Name = ((MemberExpression)m.Object).Member.Name, // Type = m.Object.GetType().ToString(), // Size = 100, // ParameterDirection = ParameterDirection.Input, // Value = (m.Arguments[0] as ConstantExpression).Value //}); SetParameter(m); return(m); case "ToUpper": this.Write("UPPER("); this.Visit(m.Object); this.Write(")"); return(m); case "ToLower": this.Write("LOWER("); this.Visit(m.Object); this.Write(")"); return(m); case "Replace": this.Write("REPLACE("); this.Visit(m.Object); this.Write(", "); this.Visit(m.Arguments[0]); this.Write(", "); this.Visit(m.Arguments[1]); this.Write(")"); return(m); case "Substring": this.Write("SUBSTRING("); this.Visit(m.Object); this.Write(", "); this.Visit(m.Arguments[0]); this.Write(" + 1, "); if (m.Arguments.Count == 2) { this.Visit(m.Arguments[1]); } else { this.Write("8000"); } this.Write(")"); return(m); case "Remove": this.Write("STUFF("); this.Visit(m.Object); this.Write(", "); this.Visit(m.Arguments[0]); this.Write(_Connector + "1, "); if (m.Arguments.Count == 2) { this.Visit(m.Arguments[1]); } else { this.Write("8000"); } this.Write(", '')"); return(m); case "IndexOf": this.Write("(CHARINDEX("); this.Visit(m.Arguments[0]); this.Write(", "); this.Visit(m.Object); if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int)) { this.Write(", "); this.Visit(m.Arguments[1]); this.Write(_Connector + "1"); } this.Write(") - 1)"); return(m); case "Trim": this.Write("RTRIM(LTRIM("); this.Visit(m.Object); this.Write("))"); return(m); } } else if (m.Method.DeclaringType.Name == "List`1") { switch (m.Method.Name) { case "Contains": this.Write("("); var position = m.Arguments[0].ToString().IndexOf(".") + 1; var length = m.Arguments[0].ToString().Length; this.Write(m.Arguments[0].ToString().Substring(position, length - position)); this.Visit(m.Object); this.Write(" in (" + inParameterString); this.Write(") )"); inParameterString = string.Empty; return(m); } } else if (m.Method.DeclaringType == typeof(DateTime)) { switch (m.Method.Name) { case "op_Subtract": if (m.Arguments[1].Type == typeof(DateTime)) { this.Write("DATEDIFF("); this.Visit(m.Arguments[0]); this.Write(", "); this.Visit(m.Arguments[1]); this.Write(")"); return(m); } break; case "AddYears": this.Write("DATEADD(YYYY,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); case "AddMonths": this.Write("DATEADD(MM,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); case "AddDays": this.Write("DATEADD(DAY,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); case "AddHours": this.Write("DATEADD(HH,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); case "AddMinutes": this.Write("DATEADD(MI,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); case "AddSeconds": this.Write("DATEADD(SS,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); case "AddMilliseconds": this.Write("DATEADD(MS,"); this.Visit(m.Arguments[0]); this.Write(","); this.Visit(m.Object); this.Write(")"); return(m); } } else if (m.Method.DeclaringType == typeof(Math)) { switch (m.Method.Name) { case "Abs": case "Acos": case "Asin": case "Atan": case "Cos": case "Exp": case "Log10": case "Sin": case "Tan": case "Sqrt": case "Sign": case "Ceiling": case "Floor": this.Write(m.Method.Name.ToUpper()); this.Write("("); this.Visit(m.Arguments[0]); this.Write(")"); return(m); case "Atan2": this.Write("ATN2("); this.Visit(m.Arguments[0]); this.Write(", "); this.Visit(m.Arguments[1]); this.Write(")"); return(m); case "Log": if (m.Arguments.Count == 1) { goto case "Log10"; } break; case "Pow": this.Write("POWER("); this.Visit(m.Arguments[0]); this.Write(", "); this.Visit(m.Arguments[1]); this.Write(")"); return(m); case "Round": if (m.Arguments.Count == 1) { this.Write("ROUND("); this.Visit(m.Arguments[0]); this.Write(", 0)"); return(m); } else if (m.Arguments.Count == 2 && m.Arguments[1].Type == typeof(int)) { this.Write("ROUND("); this.Visit(m.Arguments[0]); this.Write(", "); this.Visit(m.Arguments[1]); this.Write(")"); return(m); } break; case "Truncate": this.Write("ROUND("); this.Visit(m.Arguments[0]); this.Write(", 0, 1)"); return(m); } } if (m.Method.Name == "ToString") { if (m.Object.Type != typeof(string)) { this.Write("CONVERT(NVARCHAR, "); this.Visit(m.Object); this.Write(")"); } else { this.Visit(m.Object); } return(m); } else if (!m.Method.IsStatic && m.Method.Name == "CompareTo" && m.Method.ReturnType == typeof(int) && m.Arguments.Count == 1) { this.Write("(CASE WHEN "); this.Visit(m.Object); this.Write(" = "); this.Visit(m.Arguments[0]); this.Write(" THEN 0 WHEN "); this.Visit(m.Object); this.Write(" < "); this.Visit(m.Arguments[0]); this.Write(" THEN -1 ELSE 1 END)"); return(m); } else if (m.Method.IsStatic && m.Method.Name == "Compare" && m.Method.ReturnType == typeof(int) && m.Arguments.Count == 2) { this.Write("(CASE WHEN "); this.Visit(m.Arguments[0]); this.Write(" = "); this.Visit(m.Arguments[1]); this.Write(" THEN 0 WHEN "); this.Visit(m.Arguments[0]); this.Write(" < "); this.Visit(m.Arguments[1]); this.Write(" THEN -1 ELSE 1 END)"); return(m); } return(base.VisitMethodCall(m)); }
public override Expression Visit(BinaryOperatorNode nodeIn) { Expression left = TranslateNode(nodeIn.Left); Expression right = TranslateNode(nodeIn.Right); if (left.Type != right.Type) { Type leftType = left.Type; Type rightType = right.Type; if (OeExpressionHelper.IsNullable(left) && !OeExpressionHelper.IsNull(left)) { if (OeExpressionHelper.IsNull(right)) { right = OeConstantToVariableVisitor.NullConstantExpression; } else { leftType = Nullable.GetUnderlyingType(left.Type); } } else if (OeExpressionHelper.IsNullable(right) && !OeExpressionHelper.IsNull(right)) { if (OeExpressionHelper.IsNull(left)) { left = OeConstantToVariableVisitor.NullConstantExpression; } else { rightType = Nullable.GetUnderlyingType(right.Type); } } if (right.Type != left.Type) { if (left is ConstantExpression) { ConstantExpression oldConstant = left as ConstantExpression; ConstantExpression newConstant = OeExpressionHelper.ConstantChangeType(oldConstant, rightType); if (oldConstant != newConstant) { ReplaceConstant(oldConstant, newConstant); } left = Expression.Convert(newConstant, right.Type); } else if (right is ConstantExpression) { ConstantExpression oldConstant = right as ConstantExpression; ConstantExpression newConstant = OeExpressionHelper.ConstantChangeType(oldConstant, leftType); if (oldConstant != newConstant) { ReplaceConstant(oldConstant, newConstant); } right = Expression.Convert(newConstant, left.Type); } else { Type precedenceType = OeExpressionHelper.GetTypeConversion(left.Type, right.Type); if (left.Type != precedenceType) { left = Expression.Convert(left, precedenceType); } if (right.Type != precedenceType) { right = Expression.Convert(right, precedenceType); } } } } ExpressionType binaryType = OeExpressionHelper.ToExpressionType(nodeIn.OperatorKind); if (!(binaryType == ExpressionType.Equal || binaryType == ExpressionType.NotEqual)) { if (left.Type == typeof(String)) { Func <String, String, int> compareToFunc = String.Compare; MethodCallExpression compareToCall = Expression.Call(null, compareToFunc.GetMethodInfo(), left, right); return(Expression.MakeBinary(binaryType, compareToCall, OeConstantToVariableVisitor.ZeroStringCompareConstantExpression)); } Type underlyingType; if (left.Type.IsEnum) { Type enumUnderlyingType = Enum.GetUnderlyingType(left.Type); left = ConvertEnumExpression(left, enumUnderlyingType); right = ConvertEnumExpression(right, enumUnderlyingType); } else if ((underlyingType = Nullable.GetUnderlyingType(left.Type)) != null && underlyingType.IsEnum) { Type enumUnderlyingType = Enum.GetUnderlyingType(underlyingType); Type nullableUnderlyingType = typeof(Nullable <>).MakeGenericType(enumUnderlyingType); left = ConvertEnumExpression(left, nullableUnderlyingType); right = ConvertEnumExpression(right, nullableUnderlyingType); } } return(Expression.MakeBinary(binaryType, left, right)); UnaryExpression ConvertEnumExpression(Expression e, Type nullableType) { if (e is UnaryExpression unaryExpression) { var value = (ConstantExpression)unaryExpression.Operand; return(Expression.Convert(value, nullableType)); } return(Expression.Convert(e, nullableType)); } }
protected override Expression VisitMethodCall(MethodCallExpression expr) { Type = BinaryCriterionType.Criteria; return(expr); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsSameGenericMethod(UsingTargetMethodInfo)); }
protected override Expression VisitMethodCall(MethodCallExpression m) { if (m.Method.DeclaringType == typeof(Queryable) || m.Method.DeclaringType == typeof(Enumerable)) { switch (m.Method.Name) { case "Where": WhereArgumentsVisitor vst = new WhereArgumentsVisitor(rootCriteria); System.Linq.Expressions.Expression exp = vst.Visit(m.Arguments[1]); rootCriteria.Add(vst.CurrentCriterions[0]); break; case "Select": HandleSelect(m); break; case "First": TranslateFirst(m, false); break; case "FirstOrDefault": TranslateFirst(m, true); break; case "Single": TranslateSingle(m, false); break; case "SingleOrDefault": TranslateSingle(m, true); break; case "Count": Translation = new CountQueryTranslated(this) { Criteria = rootCriteria }; break; case "Sum": HandleProjectionOfSingleElement(m, s => NHEX.Projections.Sum(s)); break; case "Min": HandleProjectionOfSingleElement(m, s => NHEX.Projections.Min(s)); break; case "Max": HandleProjectionOfSingleElement(m, s => NHEX.Projections.Max(s)); break; case "Average": HandleProjectionOfSingleElement(m, s => NHEX.Projections.Avg(s)); break; case "GroupBy": HandleGroupBy(m); break; default: Console.WriteLine("Unknown method " + m.Method.Name); break; } } return(base.VisitMethodCall(m)); }
private static IValueExpression ParseMethodCall(string expression) { MethodCallExpression methodCall = null; int openParenIndex = expression.IndexOf("(", StringComparison.Ordinal); string memberExpression = expression.Substring(0, openParenIndex); string[] pathParts = ParseParts(memberExpression); if ((pathParts != null) && (pathParts.Length >= 2)) { methodCall = new MethodCallExpression(pathParts); } else { return null; } int paramsLength = expression.Length - openParenIndex - 2; if (paramsLength != 0) { string paramExpression = expression.Substring(openParenIndex + 1, paramsLength); string[] paramExprList = paramExpression.Split(','); for (int i = 0; i < paramExprList.Length; i++) { IValueExpression expr = ParseExpression(paramExprList[i].Trim(), /* allowMethod */ false); if (expr != null) { methodCall.AddParameter(expr); } else { return null; } } } return methodCall; }
public Expression Bind(PipelineExpression pipeline, EmbeddedPipelineBindingContext bindingContext, MethodCallExpression node, IEnumerable <Expression> arguments) { var source = pipeline.Source; if (arguments.Any()) { source = BinderHelper.BindSelect( pipeline, bindingContext, ExpressionHelper.GetLambda(arguments.Single())); } return(new PipelineExpression( source, pipeline.Projector, new AverageResultOperator( node.Type, bindingContext.GetSerializer(node.Type, node)))); }
protected virtual Expression VisitMethodCall(MethodCallExpression m) { Expression obj = this.Visit(m.Object); IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments); return this.UpdateMethodCall(m, obj, m.Method, args); }
/// <summary> /// 构造函数 /// </summary> /// <param name="node">静态方法或实例方法表达式树</param> public MethodCallVisitor(MethodCallExpression node) { this.node = node; }
static bool TryUncheckedCast(MethodCallExpression node, ref Expression rewrite) { MethodInfo info = node.Method; Type decType = info.DeclaringType; string name = info.Name; if (decType == typeof(RT)) { if (name.StartsWith("unchecked") && name.EndsWith("Cast")) { ParameterInfo[] pinfos = info.GetParameters(); if (pinfos.Length == 1 && pinfos[0].ParameterType != typeof(object)) { rewrite = Expression.Convert(node.Arguments[0], info.ReturnType); return true; } } } else if (decType == typeof(Util)) { if (name == "identical") { ParameterExpression param1 = Expression.Parameter(typeof(Object), "temp1"); ParameterExpression param2 = Expression.Parameter(typeof(Object), "temp2"); rewrite = Expression.Block(typeof(bool), new ParameterExpression[] { param1, param2 }, Expression.Assign(param1, node.Arguments[0]), Expression.Assign(param2, node.Arguments[1]), Expression.Condition( Expression.TypeIs(param1, typeof(ValueType)), Expression.Call(param1, typeof(object).GetMethod("Equals", new Type[] { typeof(object) }), param2), Expression.ReferenceEqual(param1, param2))); return true; } } else if (decType == typeof(Numbers)) { ParameterInfo[] pinfos = info.GetParameters(); bool argsOk = (pinfos.Length == 1 && (pinfos[0].ParameterType == typeof(double) || pinfos[0].ParameterType == typeof(long))) || (pinfos.Length == 2 && (pinfos[0].ParameterType == typeof(double) || pinfos[0].ParameterType == typeof(long)) && pinfos[0].ParameterType == pinfos[1].ParameterType); if (argsOk) { switch (name) { case "lt": rewrite = Expression.LessThan(node.Arguments[0], node.Arguments[1]); return true; case "lte": rewrite = Expression.LessThanOrEqual(node.Arguments[0], node.Arguments[1]); return true; case "gt": rewrite = Expression.GreaterThan(node.Arguments[0], node.Arguments[1]); return true; case "gte": rewrite = Expression.GreaterThanOrEqual(node.Arguments[0], node.Arguments[1]); return true; case "isPos": rewrite = Expression.GreaterThan(node.Arguments[0], Expression.Constant(pinfos[0].ParameterType == typeof(double) ? (object)0.0 : (object)0L)); return true; case "isNeg": rewrite = Expression.LessThan(node.Arguments[0], Expression.Constant(pinfos[0].ParameterType == typeof(double) ? (object)0.0 : (object)0L)); return true; case "isZero": rewrite = Expression.Equal(node.Arguments[0], Expression.Constant(pinfos[0].ParameterType == typeof(double) ? (object)0.0 : (object)0L)); return true; case "equiv": rewrite = Expression.Equal(node.Arguments[0], node.Arguments[1]); return true; case "unchecked_add": rewrite = Expression.Add(node.Arguments[0], node.Arguments[1]); return true; case "unchecked_minus": if (pinfos.Length == 1) rewrite = Expression.Negate(node.Arguments[0]); else rewrite = Expression.Subtract(node.Arguments[0], node.Arguments[1]); return true; case "unchecked_multiply": rewrite = Expression.Multiply(node.Arguments[0], node.Arguments[1]); return true; case "unchecked_inc": rewrite = Expression.Increment(node.Arguments[0]); return true; case "unchecked_dec": rewrite = Expression.Decrement(node.Arguments[0]); return true; } if (pinfos[0].ParameterType == typeof(double)) { switch (name) { case "add": case "addP": rewrite = Expression.Add(node.Arguments[0], node.Arguments[1]); return true; case "multiply": case "multiplyP": rewrite = Expression.Multiply(node.Arguments[0], node.Arguments[1]); return true; case "divide": rewrite = Expression.Divide(node.Arguments[0], node.Arguments[1]); return true; case "minus": case "minusP": if (pinfos.Length == 1) rewrite = Expression.Negate(node.Arguments[0]); else rewrite = Expression.Subtract(node.Arguments[0], node.Arguments[1]); return true; case "inc": case "incP": rewrite = Expression.Increment(node.Arguments[0]); return true; case "dec": case "decP": rewrite = Expression.Decrement(node.Arguments[0]); return true; } } else // long { switch (name) { case "quotient": rewrite = Expression.Divide(node.Arguments[0], node.Arguments[1]); return true; case "remainder": rewrite = Expression.Modulo(node.Arguments[0], node.Arguments[1]); return true; } } } } return false; }
}//method static MethodCallExpression MutateMethodCall(MethodCallExpression node, IList <Expression> operands) { var args = operands.Skip(1); return(node.Update(operands[0], args)); }
private string GetMethodReturnType(MethodCallExpression expression) { string result = String.Empty; switch (expression.Parent.ElementType) { case LanguageElementType.MethodCall: var MethodCall = expression.Parent as MethodCall; var index = MethodCall.Arguments.IndexOf(expression); result = GetTypeOfNthParamOfMethod(index, MethodCall); break; case LanguageElementType.MethodCallExpression: var MethodCallExpression = expression.Parent as MethodCallExpression; var MCEindex = MethodCallExpression.Arguments.IndexOf(expression); result = GetTypeOfNthParamOfMethod(MCEindex, MethodCallExpression); break; case LanguageElementType.InitializedVariable: result = GetTypeOfInitializedVariable(expression.Parent as InitializedVariable); break; case LanguageElementType.Assignment: result = GetTypeOfAssignment(expression.Parent as Assignment); break; default: throw new Exception(""); } return CodeRush.Language.GetSimpleTypeName(result); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var mergeContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); return(mergeContext); }
public abstract object EvalMethodCallExpression( object obj, MethodCallExpression exp );
protected override SequenceConvertInfo?Convert( ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression?param) { return(null); }
private static void AssertCallIsOptimized(MethodCallExpression expr, Expression instance, MethodInfo method, IReadOnlyList<Expression> args) { var n = method.GetParameters().Length; var updated = Update(expr); var visited = Visit(expr); foreach (var node in new[] { expr, updated, visited }) { Assert.Same(instance, node.Object); Assert.Same(method, node.Method); if (method.IsStatic) { AssertStaticMethodCall(n, node); } else { AssertInstanceMethodCall(n, node); } var argProvider = node as IArgumentProvider; Assert.NotNull(argProvider); Assert.Equal(n, argProvider.ArgumentCount); if (node != visited) // our visitor clones argument nodes { for (var i = 0; i < n; i++) { Assert.Same(args[i], argProvider.GetArgument(i)); Assert.Same(args[i], node.Arguments[i]); } } } }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.Method.IsGenericMethod && LinqExtensions.ExecuteMergeMethodInfo == methodCall.Method.GetGenericMethodDefinition()); }
///////////////////////////////////////////////////////////////////////////// //public override object EvalMethodCallExpression( object objIn, MethodCallExpression exp ) //{ // // ****** // // // // expression: macro.method(..) // // // // exp.MemberName should be a method on the object passed in to us, it is the // // method that we need to retreive and then invoke // // // object objResult = null; // object [] args = EvaluateArguments( exp.Arguments ); // // // ****** // Invoker invoker = Invokers.GetMethodInvoker( objIn, exp.MethodName ); // if( null != invoker ) { // objResult = invoker.Invoke( args ); // } // else { // // // // could be a "raw" delegate // // // var oInfo = new ObjectInfo( objIn, exp.MethodName ); // if( oInfo.IsDelegate ) { // objResult = oInfo.GetDelegateValue( args ); // } // else { // ThreadContext.MacroError( "there is no method or delegate named \"{0}\" on the object type \"{1}\"", exp.MethodName, ObjectInfo.GetTypeName(objIn) ); // } // } // // // ****** // CheckNullResult( objResult, objIn, exp.MethodName ); // return objResult; //} public override object EvalMethodCallExpression( object objIn, MethodCallExpression exp ) { // ****** // // expression: macro.method(..) // // exp.MemberName should be a method on the object passed in to us, it is the // method that we need to retreive and then invoke // object objResult = null; object [] args = EvaluateArguments( exp.Arguments ); // ****** //Invoker invoker = Invokers.GetMethodInvoker( objIn, exp.MethodName ); Invoker invoker = Invokers.GetMethodInvoker( objIn, exp.MethodName, typeHelpers ); if( null != invoker ) { objResult = invoker.Invoke( args ); } else { // // could be a "raw" delegate // var oInfo = new ObjectInfo( objIn, exp.MethodName ); if( oInfo.IsDelegate ) { objResult = oInfo.GetDelegateValue( args ); } else { ThreadContext.MacroError( "there is no method or delegate named \"{0}\" on the object type \"{1}\"", exp.MethodName, ObjectInfo.GetTypeName(objIn) ); } } // ****** CheckNullResult( objResult, objIn, exp.MethodName ); return objResult; }
public static bool GetSqlExtensionMethodCallConstant(ITranslator translator, MethodCallExpression methodExpression, Parameters parameters, out string concat) { if (methodExpression.Method.Name == "Min" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("MIN(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } if (methodExpression.Method.Name == "Max" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("MAX(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } if (methodExpression.Method.Name == "Sum" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("SUM(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } if (methodExpression.Method.Name == "As" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { var aliasFormat = translator.GetAliasFormat(); var alias = string.Format(aliasFormat, Convert.ToString(methodExpression.Arguments[1]).Replace("\"", "").Replace("'", "")); concat = string.Concat(GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " AS ", alias); return(true); } if (methodExpression.Method.Name == "Between" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " BETWEEN ", GetStringForExpression(translator, methodExpression.Arguments[1], parameters), " AND ", GetStringForExpression(translator, methodExpression.Arguments[2], parameters), ")"); return(true); } if (methodExpression.Method.Name == "In" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " IN (", GetStringForExpression(translator, methodExpression.Arguments[1], parameters), "))"); return(true); } if (methodExpression.Method.Name == "Like" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " LIKE ", GetStringForExpression(translator, methodExpression.Arguments[1], parameters), ")"); return(true); } if (methodExpression.Method.Name == "TrimSql" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("LTRIM(RTRIM(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), "))"); return(true); } if (methodExpression.Method.Name == "Length" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { var lengthName = translator.GetLengthFunctionName(); concat = string.Concat(lengthName, "(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } if (methodExpression.Method.Name == "Upper" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("UPPER(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } if (methodExpression.Method.Name == "Lower" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("LOWER(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } if (methodExpression.Method.Name == "IsNull" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { var isNullName = translator.GetIsNullFunctionName(); concat = string.Concat(isNullName, "(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ",", GetStringForExpression(translator, methodExpression.Arguments[1], parameters), ")"); return(true); } if (methodExpression.Method.Name == "Cast" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { var returnDbType = TableDefinition.GetTypeForProperty(methodExpression.Method.ReturnType); concat = string.Concat("CAST(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), " AS ", translator.GetTextFor(new FieldDefinition { Type = returnDbType }, true), ")"); return(true); } if (methodExpression.Method.Name == "Average" && methodExpression.Method.ReflectedType.Name == "SqlExtensions") { concat = string.Concat("AVG(", GetStringForExpression(translator, methodExpression.Arguments[0], parameters), ")"); return(true); } concat = ""; return(false); }
private static MethodCallExpression UpdateArgs(MethodCallExpression node) { // Tests the call of Update to Expression.Call factories. MethodCallExpression res = node.Update(node.Object, node.Arguments.ToArray()); Assert.NotSame(node, res); return res; }
protected override Expression VisitSQLNewGuid(MethodCallExpression m) { _builder.Append("SYS_GUID()"); return(m); }
private static MethodCallExpression VisitObj(MethodCallExpression node) { // Tests dispatch of ExpressionVisitor into Rewrite method which calls Expression.Call factories. return (MethodCallExpression)new VisitorObj().Visit(node); }
protected override Expression VisitMethodCall(MethodCallExpression node) { if (node.Method.DeclaringType == typeof(Queryable) && node.Method.Name == "Select") { var select = Visit(node.Arguments[0]); var projection = Visit(StripQuotes(node.Arguments[1])) as LambdaExpression; if (projection == null) { throw new NotSupportedException("Performing a select without a lambda is not supported"); } return(new SelectExpression(node.Type, select, projection)); } if (node.Method.DeclaringType == typeof(Queryable) && node.Method.Name == "Where") { var select = Visit(node.Arguments[0]); var filter = Visit(StripQuotes(node.Arguments[1])); return(new WhereExpression(node.Type, select, filter)); } if (node.Method.DeclaringType == typeof(Queryable) && (node.Method.Name == "OrderBy" || node.Method.Name == "ThenBy")) { var source = Visit(node.Arguments[0]); var orderSelector = Visit(StripQuotes(node.Arguments[1])); return(new OrderExpression(node.Type, source, orderSelector, OrderOptions.Ascending)); } if (node.Method.DeclaringType == typeof(Queryable) && (node.Method.Name == "OrderByDescending" || node.Method.Name == "ThenByDescending")) { var source = Visit(node.Arguments[0]); var orderSelector = Visit(StripQuotes(node.Arguments[1])); return(new OrderExpression(node.Type, source, orderSelector, OrderOptions.Descending)); } if (node.Method.DeclaringType == typeof(string) && node.Method.Name == "StartsWith") { var subject = Visit(node.Object); var target = Visit(node.Arguments[0]); return(new UnderExpression(node.Type, subject, target)); } if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "WasEver") { var subject = Visit(node.Arguments[0]); var target = Visit(node.Arguments[1]); return(new WasEverExpression(node.Type, subject, target)); } if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "InGroup") { var subject = Visit(node.Arguments[0]); var target = Visit(node.Arguments[1]); return(new InGroupExpression(node.Type, subject, target)); } if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "NotInGroup") { var subject = Visit(node.Arguments[0]); var target = Visit(node.Arguments[1]); return(new NotInGroupExpression(node.Type, subject, target)); } // This is a contains used to see if a value is in a list, such as: bug => aliases.Contains(bug.AssignedTo) if (node.Method.DeclaringType == typeof(Enumerable) && node.Method.Name == "Contains") { var subject = Visit(node.Arguments[1]); var target = Visit(node.Arguments[0]); return(new InExpression(node.Type, subject, target)); } // This is a contains used to do substring matching on a value, such as: bug => bug.Status.Contains("Approved") if (node.Method.DeclaringType == typeof(string) && node.Method.Name == "Contains") { var subject = Visit(node.Object); var target = Visit(node.Arguments[0]); return(new ContainsExpression(node.Type, subject, target)); } if (node.Method.DeclaringType == typeof(QueryExtensions) && node.Method.Name == "AsOf") { Visit(node.Arguments[0]); var time = (ConstantExpression)Visit(node.Arguments[1]); return(new AsOfExpression(node.Type, (DateTime)time.Value)); } if (node.Method.Name == "ToUpper" || node.Method.Name == "ToUpperInvariant" || node.Method.Name == "ToLower" || node.Method.Name == "ToLowerInvariant") { throw new NotSupportedException($"The method {node.Method.Name} is not supported. Queries are case insensitive, so string comparisons should use the regular operators ( ==, > <=, etc.)"); } if (node.Method.Name == "ToString") { return(Expression.TypeAs(Visit(node.Object), typeof(string))); } if (node.Method.Name == "get_Item") { var subject = node.Object; var name = Visit(node.Arguments[0]); return(new IndexerExpression(node.Type, subject, name)); } // Unknown method call throw new NotSupportedException($"The method '{node.Method.Name}' is not supported"); }
protected internal virtual void PostWalk(MethodCallExpression node) { }
public static Criterion From(MethodCallExpression expression, bool throwOnError = true) { Expression valueExpression = null; MemberExpression propertyExpression; FilterFunction filter; string sql = null; if (expression.Method == StringContainsMethod) { propertyExpression = expression.Object as MemberExpression; valueExpression = expression.Arguments[0]; filter = FilterFunction.Contains; } else if (expression.Method == StringContainsExtensionMethod) { propertyExpression = expression.Arguments[0] as MemberExpression; valueExpression = expression.Arguments[1]; filter = FilterFunction.Contains; } else if (expression.Method == StringIsEmptyExtensionMethod) { propertyExpression = expression.Arguments[0] as MemberExpression; var column = propertyExpression.GetDatabaseColumnPath(); return(new BinaryCriterion(new Criterion(column, value: null), BinaryOperator.OR, new Criterion(column, string.Empty))); } else if (expression.Method == StringHasValueExtensionMethod) { propertyExpression = expression.Arguments[0] as MemberExpression; var column = propertyExpression.GetDatabaseColumnPath(); return(new BinaryCriterion(new Criterion(column, FilterFunction.IsNot, value: null), BinaryOperator.AND, new Criterion(column, FilterFunction.IsNot, string.Empty))); } else if (expression.Method == StringLacksExtensionMethod) { propertyExpression = expression.Arguments[0] as MemberExpression; valueExpression = expression.Arguments[1]; filter = FilterFunction.NotContains; } else if (expression.Method == StringStartsWithMethod) { propertyExpression = expression.Object as MemberExpression; valueExpression = expression.Arguments[0]; filter = FilterFunction.BeginsWith; } else if (expression.Method == StringEndsWithMethod) { propertyExpression = expression.Object as MemberExpression; valueExpression = expression.Arguments[0]; filter = FilterFunction.EndsWith; } else if (expression.Method.Name == "IsAnyOf") { propertyExpression = expression.Arguments.First() as MemberExpression; valueExpression = expression.Arguments[1]; filter = FilterFunction.In; } else if (expression.Method.Name == "IsNoneOf") { propertyExpression = expression.Arguments.First() as MemberExpression; valueExpression = expression.Arguments[1]; filter = FilterFunction.NotIn; } else { if (!throwOnError) { return(null); } throw new ArgumentException("Invalid database criteria. The provided filter expression cannot be evaluated and converted into a SQL condition."); } if (propertyExpression == null || !(propertyExpression.Member is PropertyInfo)) { if (!throwOnError) { return(null); } throw new ArgumentException("Invalid database criteria. The provided filter expression cannot be evaluated and converted into a SQL condition." + expression + Environment.NewLine + Environment.NewLine + "Consider using application level filter using the \".Where(...)\" clause."); } var property = propertyExpression.Member.Name; // Middle properties? while (propertyExpression.Expression is MemberExpression) { propertyExpression = propertyExpression.Expression as MemberExpression; property = propertyExpression.Member.Name + "." + property; } if (sql.HasValue()) { if (property.Contains(".")) { return(null); // Nesting is not supported. } return(new DirectDatabaseCriterion(sql.Replace("#PROPERTY#", property)) { PropertyName = property }); } else { var value = Expression.Lambda(valueExpression).Compile().DynamicInvoke(); if (!(value is string) && value is IEnumerable asEnum) { Func <object, string> escape = x => $"'{x}'"; if (asEnum.GetType().GetEnumerableItemType().IsBasicNumeric()) { escape = x => x.ToString(); } if (asEnum.GetType().GetEnumerableItemType().Implements <IEntity>()) { escape = x => $"'{(x as IEntity).GetId()}'"; } if (asEnum.GetType().GetEnumerableItemType().IsEnum) { escape = x => ((int)x).ToString(); } value = $"({asEnum.Cast<object>().Select(escape).ToString(",")})"; } return(new Criterion(property, filter, value)); } }
private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpression mc, ParameterExpression[] paramList, Expression[] argList) { Debug.Assert(TypeUtils.AreEquivalent(TypeUtils.GetNonNullableType(resultType), TypeUtils.GetNonNullableType(mc.Type))); switch (nodeType) { default: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: { Label exit = _ilg.DefineLabel(); Label exitNull = _ilg.DefineLabel(); LocalBuilder anyNull = _ilg.DeclareLocal(typeof(bool)); for (int i = 0, n = paramList.Length; i < n; i++) { ParameterExpression v = paramList[i]; Expression arg = argList[i]; if (TypeUtils.IsNullableType(arg.Type)) { _scope.AddLocal(this, v); EmitAddress(arg, arg.Type); _ilg.Emit(OpCodes.Dup); _ilg.EmitHasValue(arg.Type); _ilg.Emit(OpCodes.Ldc_I4_0); _ilg.Emit(OpCodes.Ceq); _ilg.Emit(OpCodes.Stloc, anyNull); _ilg.EmitGetValueOrDefault(arg.Type); _scope.EmitSet(v); } else { _scope.AddLocal(this, v); EmitExpression(arg); if (!arg.Type.GetTypeInfo().IsValueType) { _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Ldnull); _ilg.Emit(OpCodes.Ceq); _ilg.Emit(OpCodes.Stloc, anyNull); } _scope.EmitSet(v); } _ilg.Emit(OpCodes.Ldloc, anyNull); _ilg.Emit(OpCodes.Brtrue, exitNull); } EmitMethodCallExpression(mc); if (TypeUtils.IsNullableType(resultType) && !TypeUtils.AreEquivalent(resultType, mc.Type)) { ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type }); _ilg.Emit(OpCodes.Newobj, ci); } _ilg.Emit(OpCodes.Br_S, exit); _ilg.MarkLabel(exitNull); if (TypeUtils.AreEquivalent(resultType, TypeUtils.GetNullableType(mc.Type))) { if (resultType.GetTypeInfo().IsValueType) { LocalBuilder result = GetLocal(resultType); _ilg.Emit(OpCodes.Ldloca, result); _ilg.Emit(OpCodes.Initobj, resultType); _ilg.Emit(OpCodes.Ldloc, result); FreeLocal(result); } else { _ilg.Emit(OpCodes.Ldnull); } } else { switch (nodeType) { case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: _ilg.Emit(OpCodes.Ldc_I4_0); break; default: throw Error.UnknownLiftType(nodeType); } } _ilg.MarkLabel(exit); return; } case ExpressionType.Equal: case ExpressionType.NotEqual: { if (TypeUtils.AreEquivalent(resultType, TypeUtils.GetNullableType(mc.Type))) { goto default; } Label exit = _ilg.DefineLabel(); Label exitAllNull = _ilg.DefineLabel(); Label exitAnyNull = _ilg.DefineLabel(); LocalBuilder anyNull = _ilg.DeclareLocal(typeof(bool)); LocalBuilder allNull = _ilg.DeclareLocal(typeof(bool)); _ilg.Emit(OpCodes.Ldc_I4_0); _ilg.Emit(OpCodes.Stloc, anyNull); _ilg.Emit(OpCodes.Ldc_I4_1); _ilg.Emit(OpCodes.Stloc, allNull); for (int i = 0, n = paramList.Length; i < n; i++) { ParameterExpression v = paramList[i]; Expression arg = argList[i]; _scope.AddLocal(this, v); if (TypeUtils.IsNullableType(arg.Type)) { EmitAddress(arg, arg.Type); _ilg.Emit(OpCodes.Dup); _ilg.EmitHasValue(arg.Type); _ilg.Emit(OpCodes.Ldc_I4_0); _ilg.Emit(OpCodes.Ceq); _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Ldloc, anyNull); _ilg.Emit(OpCodes.Or); _ilg.Emit(OpCodes.Stloc, anyNull); _ilg.Emit(OpCodes.Ldloc, allNull); _ilg.Emit(OpCodes.And); _ilg.Emit(OpCodes.Stloc, allNull); _ilg.EmitGetValueOrDefault(arg.Type); } else { EmitExpression(arg); if (!arg.Type.GetTypeInfo().IsValueType) { _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Ldnull); _ilg.Emit(OpCodes.Ceq); _ilg.Emit(OpCodes.Dup); _ilg.Emit(OpCodes.Ldloc, anyNull); _ilg.Emit(OpCodes.Or); _ilg.Emit(OpCodes.Stloc, anyNull); _ilg.Emit(OpCodes.Ldloc, allNull); _ilg.Emit(OpCodes.And); _ilg.Emit(OpCodes.Stloc, allNull); } else { _ilg.Emit(OpCodes.Ldc_I4_0); _ilg.Emit(OpCodes.Stloc, allNull); } } _scope.EmitSet(v); } _ilg.Emit(OpCodes.Ldloc, allNull); _ilg.Emit(OpCodes.Brtrue, exitAllNull); _ilg.Emit(OpCodes.Ldloc, anyNull); _ilg.Emit(OpCodes.Brtrue, exitAnyNull); EmitMethodCallExpression(mc); if (TypeUtils.IsNullableType(resultType) && !TypeUtils.AreEquivalent(resultType, mc.Type)) { ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type }); _ilg.Emit(OpCodes.Newobj, ci); } _ilg.Emit(OpCodes.Br_S, exit); _ilg.MarkLabel(exitAllNull); _ilg.EmitBoolean(nodeType == ExpressionType.Equal); _ilg.Emit(OpCodes.Br_S, exit); _ilg.MarkLabel(exitAnyNull); _ilg.EmitBoolean(nodeType == ExpressionType.NotEqual); _ilg.MarkLabel(exit); return; } } }
static bool TryUncheckedCast(MethodCallExpression node, ref Expression rewrite) { MethodInfo info = node.Method; Type decType = info.DeclaringType; string name = info.Name; if (decType == typeof(RT)) { switch (name) { case "doubleCast": case "uncheckedDoubleCast": case "longCast": case "uncheckedIntCast": case "uncheckedLongCast": { ParameterInfo[] pinfos = info.GetParameters(); if (pinfos.Length == 1 && pinfos[0].ParameterType != typeof(object)) { rewrite = Expression.Convert(node.Arguments[0], info.ReturnType); return true; } } break; case "aget": { ParameterInfo[] pinfos = info.GetParameters(); if (pinfos.Length == 2 && pinfos[0].ParameterType.IsArray) { rewrite = Expression.ArrayIndex(node.Arguments[0], node.Arguments[1]); return true; } } break; case "alength": { ParameterInfo[] pinfos = info.GetParameters(); if (pinfos.Length == 1 && pinfos[0].ParameterType.IsArray) { rewrite = Expression.ArrayLength(node.Arguments[0]); return true; } } break; } } else if (decType == typeof(Util)) { if (name == "identical") { ParameterExpression param1 = Expression.Parameter(typeof(Object), "temp1"); ParameterExpression param2 = Expression.Parameter(typeof(Object), "temp2"); rewrite = Expression.Block(typeof(bool), new ParameterExpression[] { param1, param2 }, Expression.Assign(param1, node.Arguments[0]), Expression.Assign(param2, node.Arguments[1]), Expression.Condition( Expression.TypeIs(param1, typeof(ValueType)), Expression.Call(param1, typeof(object).GetMethod("Equals", new Type[] { typeof(object) }), param2), Expression.ReferenceEqual(param1, param2))); return true; } else if (name == "equiv") { ParameterInfo[] pinfos = info.GetParameters(); if (pinfos.Length == 2 && pinfos[0].ParameterType == pinfos[1].ParameterType && (pinfos[0].ParameterType == typeof(long) || pinfos[0].ParameterType == typeof(double) || pinfos[0].ParameterType == typeof(bool))) { rewrite = Expression.Equal(node.Arguments[0], node.Arguments[1]); return true; } } } else if (decType == typeof(Numbers)) { ParameterInfo[] pinfos = info.GetParameters(); if (pinfos.Length == 1) { Type t0 = pinfos[0].ParameterType; Expression arg0 = node.Arguments[0]; if (t0 == typeof(double)) { switch (name) { case "minus": case "unchecked_minus": rewrite = Expression.Negate(arg0); return true; case "inc": case "unchecked_inc": rewrite = Expression.Increment(arg0); return true; case "dec": case "unchecked_dec": rewrite = Expression.Decrement(arg0); return true; case "isZero": rewrite = Expression.Equal(arg0, Expression.Constant(0.0)); return true; case "isPos": rewrite = Expression.GreaterThan(arg0, Expression.Constant(0.0)); return true; case "isNeg": rewrite = Expression.LessThan(arg0, Expression.Constant(0.0)); return true; } } else if (t0 == typeof(long)) { switch (name) { case "unchecked_minus": rewrite = Expression.Negate(arg0); return true; case "unchecked_inc": rewrite = Expression.Increment(arg0); return true; case "unchecked_dec": rewrite = Expression.Decrement(arg0); return true; case "isZero": rewrite = Expression.Equal(arg0, Expression.Constant(0L)); return true; case "isPos": rewrite = Expression.GreaterThan(arg0, Expression.Constant(0L)); return true; case "isNeg": rewrite = Expression.LessThan(arg0, Expression.Constant(0L)); return true; } } else if (t0 == typeof(int)) { switch (name) { case "unchecked_int_negate": rewrite = Expression.Negate(arg0); return true; case "unchecked_int_inc": rewrite = Expression.Increment(arg0); return true; case "unchecked_int_dec": rewrite = Expression.Decrement(arg0); return true; } } } else if (pinfos.Length == 2 && pinfos[0].ParameterType == pinfos[1].ParameterType) { Type t0 = pinfos[0].ParameterType; Expression arg0 = node.Arguments[0]; Expression arg1 = node.Arguments[1]; if (t0 == typeof(double)) { switch (name) { case "add": case "unchecked_add": rewrite = Expression.Add(arg0, arg1); return true; case "multiply": case "unchecked_multiply": rewrite = Expression.Multiply(arg0, arg1); return true; case "divide": rewrite = Expression.Divide(arg0, arg1); return true; case "minus": case "unchecked_minus": rewrite = Expression.Subtract(arg0, arg1); return true; case "lt": rewrite = Expression.LessThan(arg0, arg1); return true; case "lte": rewrite = Expression.LessThanOrEqual(arg0, arg1); return true; case "gt": rewrite = Expression.GreaterThan(arg0, arg1); return true; case "gte": rewrite = Expression.GreaterThanOrEqual(arg0, arg1); return true; case "equiv": rewrite = Expression.Equal(arg0, arg1); return true; } } else if (t0 == typeof(long)) { switch (name) { case "and": rewrite = Expression.And(arg0, arg1); return true; case "or": rewrite = Expression.Or(arg0, arg1); return true; case "xor": rewrite = Expression.ExclusiveOr(arg0, arg1); return true; case "remainder": rewrite = Expression.Modulo(arg0, arg1); return true; case "shiftLeft": rewrite = Expression.LeftShift(arg0, Expression.Convert(arg1,typeof(int))); return true; case "shiftRight": rewrite = Expression.RightShift(arg0, Expression.Convert(arg1,typeof(int))); return true; case "quotient": rewrite = Expression.Divide(arg0, arg1); return true; case "unchecked_add": rewrite = Expression.Add(arg0, arg1); return true; case "unchecked_minus": rewrite = Expression.Subtract(arg0, arg1); return true; case "unchecked_multiply": rewrite = Expression.Multiply(arg0, arg1); return true; case "lt": rewrite = Expression.LessThan(arg0, arg1); return true; case "lte": rewrite = Expression.LessThanOrEqual(arg0, arg1); return true; case "gt": rewrite = Expression.GreaterThan(arg0, arg1); return true; case "gte": rewrite = Expression.GreaterThanOrEqual(arg0, arg1); return true; case "equiv": rewrite = Expression.Equal(arg0, arg1); return true; } } else if (t0 == typeof(int)) { switch (name) { case "shiftLeftInt": rewrite = Expression.LeftShift(arg0, arg1); return true; case "shiftRightInt": rewrite = Expression.RightShift(arg0, arg1); return true; case "unchecked_int_add": rewrite = Expression.Add(arg0, arg1); return true; case "unchecked_int_subtract": rewrite = Expression.Subtract(arg0, arg1); return true; case "unchecked_int_multiply": rewrite = Expression.Multiply(arg0, arg1); return true; case "unchecked_int_divide": rewrite = Expression.Divide(arg0, arg1); return true; case "unchecked_int_remainder": rewrite = Expression.Modulo(arg0, arg1); return true; } } } } return false; }