private CodeExpression VisitMethodCall(MethodCallExpression methodCallExpression) { var mr = GetMethodRef(methodCallExpression.Method); if (methodCallExpression.Object == null) { if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.VarRef" || mr.MethodName == "LinqToCodedom.Generator.CodeDom.ParamRef") { return(new LinqToCodedom.Generator.CodeDom.CodeVarExpression( CodeDom.Eval <string>(methodCallExpression.Arguments[0]))); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.TypeRef") { var c = new CodeTypeReferenceExpression( CodeDom.Eval <string>(methodCallExpression.Arguments[0])); if (methodCallExpression.Arguments.Count == 2) { NewArrayExpression arr = methodCallExpression.Arguments[1] as NewArrayExpression; foreach (Expression ee in arr.Expressions) { object t = CodeDom.Eval(ee); c.Type.TypeArguments.Add(CodeDom.GetTypeReference(t)); } } return(c); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.TypeOf") { var c = new CodeTypeOfExpression( CodeDom.Eval <string>(methodCallExpression.Arguments[0])); if (methodCallExpression.Arguments.Count == 2) { NewArrayExpression arr = methodCallExpression.Arguments[1] as NewArrayExpression; foreach (Expression ee in arr.Expressions) { object t = CodeDom.Eval(ee); c.Type.TypeArguments.Add(CodeDom.GetTypeReference(t)); } } return(c); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.get_nil") { return(null); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.Property") { CodeExpression targetExp = _Visit(methodCallExpression.Arguments[0]); if (targetExp is CodePrimitiveExpression && ((CodePrimitiveExpression)targetExp).Value == null) { targetExp = null; } return(new CodePropertyReferenceExpression( targetExp, CodeDom.Eval <string>(methodCallExpression.Arguments[1]))); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.Field") { object val = null; try { val = CodeDom.Eval(methodCallExpression.Arguments[0]); } catch (Exception) { } if (val != null && val is CodeTypeReference) { return(new CodeFieldReferenceExpression( new CodeTypeReferenceExpression((CodeTypeReference)val), CodeDom.Eval <string>(methodCallExpression.Arguments[1]))); } else { CodeExpression targetExp = _Visit(methodCallExpression.Arguments[0]); if (targetExp is CodePrimitiveExpression && ((CodePrimitiveExpression)targetExp).Value == null) { targetExp = null; } return(new CodeFieldReferenceExpression( targetExp, CodeDom.Eval <string>(methodCallExpression.Arguments[1]))); } } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.Call") { if (methodCallExpression.Arguments.Count == 1) { return(new CodeMethodInvokeExpression( null, CodeDom.Eval <string>(methodCallExpression.Arguments[0]))); } else { CodeExpression targetExp = _Visit(methodCallExpression.Arguments[0]); if (targetExp is CodePrimitiveExpression && ((CodePrimitiveExpression)targetExp).Value == null) { targetExp = null; } var m = new CodeMethodReferenceExpression( targetExp, CodeDom.Eval <string>(methodCallExpression.Arguments[1])); if (methodCallExpression.Arguments.Count == 3) { foreach (Expression e in (methodCallExpression.Arguments[2] as NewArrayExpression).Expressions) { m.TypeArguments.Add(CodeDom.GetTypeReference(CodeDom.Eval(e))); } } return(new CodeMethodInvokeExpression(m)); } } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.new") { object t = CodeDom.Eval(methodCallExpression.Arguments[0]); CodeTypeReference type = CodeDom.GetTypeReference(t); if (methodCallExpression.Arguments.Count == 2) { NewArrayExpression arr = methodCallExpression.Arguments[1] as NewArrayExpression; var exp = new CodeObjectCreateExpression(type); foreach (Expression par in arr.Expressions) { AddParam(exp.Parameters, par); } return(exp); } else { return(new CodeObjectCreateExpression(type)); } } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.cast") { object t = CodeDom.Eval(methodCallExpression.Arguments[0]); CodeTypeReference type = CodeDom.GetTypeReference(t); if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.GetGenericArguments()[0] == typeof(Var)) { return(new CodeDom.CodeWrapExpression(new CodeCastExpression(type, _Visit(methodCallExpression.Arguments[1])))); } else { return(new CodeCastExpression(type, _Visit(methodCallExpression.Arguments[1]))); } } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.default") { object t = CodeDom.Eval(methodCallExpression.Arguments[0]); CodeTypeReference type = CodeDom.GetTypeReference(t); return(new CodeDefaultValueExpression(type)); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.InjectExp") { int num = CodeDom.Eval <int>(methodCallExpression.Arguments[0]); return(_ctx.Injections[num]); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.Is") { return(new CodeIdentityEqualityExpression( true, _Visit(methodCallExpression.Arguments[0]), _Visit(methodCallExpression.Arguments[1]) )); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.IsNot") { return(new CodeIdentityEqualityExpression( false, _Visit(methodCallExpression.Arguments[0]), _Visit(methodCallExpression.Arguments[1]) )); } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.Lambda") { if (methodCallExpression.Arguments[0].Type.IsArray) { List <LambdaParam> pars = new List <LambdaParam>(); foreach (LambdaParam lambdaParam in CodeDom.Eval <IEnumerable>(methodCallExpression.Arguments[0])) { pars.Add(lambdaParam); } List <CodeStatement> stmts = new List <CodeStatement>(); foreach (CodeStatement stmt in CodeDom.Eval <IEnumerable>(methodCallExpression.Arguments[1])) { stmts.Add(stmt); } return(new CodeLambdaStatements(stmts, pars)); } else { CodeExpression exp = _Visit(methodCallExpression.Arguments[0]); List <LambdaParam> pars = new List <LambdaParam>(); if (methodCallExpression.Arguments.Count == 2) { NewArrayExpression arr = methodCallExpression.Arguments[1] as NewArrayExpression; foreach (Expression par in arr.Expressions) { pars.Add(CodeDom.Eval <LambdaParam>(par)); } } return(new CodeLambdaExpression(exp, pars)); } } else if (mr.MethodName == "LinqToCodedom.Generator.CodeDom.CallDelegate") { CodeExpression target = null; if (methodCallExpression.Arguments[0].Type == typeof(string)) { target = new CodeVariableReferenceExpression(CodeDom.Eval <string>(methodCallExpression.Arguments[0])); } else { target = _Visit(methodCallExpression.Arguments[0]); } var d = new CodeDelegateInvokeExpression(target); return(d); } } var to = _Visit(methodCallExpression.Object); if (to is CodeDom.CodeThisExpression || to is CodeDom.CodeBaseExpression || to is CodeDom.CodeVarExpression || to is CodeDom.CodeWrapExpression) { CodeExpression rto = to is CodeDom.CodeThisExpression ? new CodeThisReferenceExpression() : to is CodeDom.CodeBaseExpression ? new CodeBaseReferenceExpression() : to is CodeVariableReferenceExpression ? to as CodeVariableReferenceExpression : to; switch (mr.MethodName) { case "Call": //case "CallFunction": if (methodCallExpression.Arguments.Count > 0) { var m = new CodeMethodReferenceExpression( rto, CodeDom.Eval <string>(methodCallExpression.Arguments[0])); if (methodCallExpression.Arguments.Count == 2) { foreach (Expression e in (methodCallExpression.Arguments[1] as NewArrayExpression).Expressions) { m.TypeArguments.Add(CodeDom.GetTypeReference(CodeDom.Eval(e))); } } return(new CodeMethodInvokeExpression(m)); } else { return(new CodeDelegateInvokeExpression(rto)); } case "Property": string propertyName = CodeDom.Eval <string>(methodCallExpression.Arguments[0]); if (methodCallExpression.Arguments.Count > 1) { throw new NotImplementedException(); } return(new CodeDom.CodeWrapExpression(new CodePropertyReferenceExpression(rto, propertyName))); //return new CodePropertyReferenceExpression(rto, propertyName); case "Field": string fieldName = CodeDom.Eval <string>(methodCallExpression.Arguments[0]); if (methodCallExpression.Arguments.Count > 1) { throw new NotImplementedException(); } return(new CodeFieldReferenceExpression(rto, fieldName)); case "Raise": string eventName = CodeDom.Eval <string>(methodCallExpression.Arguments[0]); return(new CodeDom.CodeDelegateArgsInvoke( new CodeEventReferenceExpression(rto, eventName))); case "ArrayGet": return(new CodeArrayIndexerExpression(rto, VisitExpressionList((methodCallExpression.Arguments[0] as NewArrayExpression).Expressions).ToArray() )); case "JaggedArrayGet": var n = methodCallExpression.Arguments[0] as NewArrayExpression; CodeArrayIndexerExpression prev = null; foreach (CodeExpression e in VisitExpressionList(n.Expressions.Reverse())) { if (prev == null) { prev = new CodeArrayIndexerExpression(rto, e); } else { prev = new CodeArrayIndexerExpression(prev, e); } } return(prev); case "cast": return(rto); default: throw new NotImplementedException(mr.MethodName); } } //else if (to is CodeDom.CodeArgsInvoke) //{ // var c = to as CodeMethodInvokeExpression; // c.Parameters.AddRange(VisitArguments(methodCallExpression.Arguments)); // //foreach (CodeExpression par in VisitSequence( // // new QueryVisitor((e) => e is LambdaExpression) // // .Visit(methodCallExpression.Arguments[0]) as LambdaExpression)) // //{ // // c.Parameters.Add(par); // //} // return c; //} //else if (to is CodeDom.CodeDelegateArgsInvoke) //{ // var c = to as CodeDelegateInvokeExpression; // c.Parameters.AddRange(VisitArguments(methodCallExpression.Arguments)); // //foreach (CodeExpression par in VisitSequence( // // new QueryVisitor((e) => e is LambdaExpression) // // .Visit(methodCallExpression.Arguments[0]) as LambdaExpression)) // //{ // // c.Parameters.Add(par); // //} // return c; //} else { if ((methodCallExpression.Object != null && methodCallExpression.Object.Type.IsArray && mr.MethodName == "Get") || (mr.MethodName == "get_Item" && methodCallExpression.Method.IsSpecialName)) { var c = new CodeArrayIndexerExpression(); foreach (var par in methodCallExpression.Arguments) { AddParam(c.Indices, par); } c.TargetObject = to; return(c); } else { var c = new CodeMethodInvokeExpression(mr); foreach (var par in methodCallExpression.Arguments) { AddParam(c.Parameters, par); } c.Method.TargetObject = to; return(c); } } }