public JsNode VisitMethodGroupResolveResult(MethodGroupResolveResult res) { var info = res.GetInfo(); IMethod me; if (info != null && info.Conversion != null && info.Conversion.Method != null) { me = info.Conversion.Method; } else //happens when invoking a method with overloads, and a parameter is dynamic { var list = res.Methods.ToList(); if (list.Count == 0) { throw new Exception("Method group not resolved to any method"); } else if (list.Count == 1) { me = list[0]; } else { me = list[0]; } //TODO: verify all methods has the same js name } var isExtensionMethodStyle = me.IsExtensionMethod && !(res.TargetResult is TypeResolveResult) && info != null && info.Conversion != null && info.Conversion.DelegateCapturesFirstArgument;//TODO: IsExtensionMethodStyle(new CsInvocationExpression { entity = me, expression = node }); JsExpression firstPrm = null; if (isExtensionMethodStyle) { firstPrm = (JsExpression)Visit(res.TargetResult); } var node2 = SkJs.EntityToMember(me); JsExpression node3; JsExpression instanceContext = null; if (me.IsStatic || res.TargetResult == null) //getting ThisResolveResult even on static methods, getting TargetResult=null when MethodGroupResolveResult when using delegates { node3 = node2; } else { instanceContext = VisitExpression(res.TargetResult); node3 = instanceContext.Member(node2); } if (info != null && (instanceContext != null || firstPrm != null)) { var conv = info.Conversion; if (info.ConversionTargetType != null && !UseNativeFunctions(info.ConversionTargetType))//delegate type { var parentMethod = info.Nodes.FirstOrDefault().GetCurrentMethod(); if (parentMethod == null || !Sk.ForceDelegatesAsNativeFunctions(parentMethod)) { if (parentMethod == null) { Log.Warn(info.Nodes.FirstOrDefault(), "GetParentMethod() returned null"); } var func = (JsExpression)node2; if (instanceContext != null) { node3 = CreateJsDelegate(instanceContext, func); } else if (firstPrm != null) { node3 = CreateJsExtensionDelegate(firstPrm, func); } } } } return(node3); }
JsNode CreateJsDelegateIfNeeded(JsFunction func, IMember currentMember, IType delType, bool isAnonymous) { if (currentMember != null && !currentMember.IsStatic && !UseNativeFunctions(delType) && !Sk.ForceDelegatesAsNativeFunctions(currentMember)) { var instanceContext = new JsThis(); JsExpression wrapper; if (isAnonymous) { wrapper = CreateAnonymousJsDelegate(instanceContext, func); } else { wrapper = CreateJsDelegate(instanceContext, func); } return(wrapper); } else { return(func); } }
public JsNode VisitMethodGroupResolveResult(MethodGroupResolveResult res) { var info = res.GetInfo(); IMethod me; if (info != null && info.Conversion != null && info.Conversion.Method != null) { me = info.Conversion.Method; } else //happens when invoking a method with overloads, and a parameter is dynamic { var list = res.Methods.ToList(); if (list.Count == 0) { throw new Exception("Method group not resolved to any method"); } else if (list.Count == 1) { me = list[0]; } else { me = list[0]; } //TODO: verify all methods has the same js name } var isExtensionMethodStyle = me.IsExtensionMethod && !(res.TargetResult is TypeResolveResult) && info != null && info.Conversion != null && info.Conversion.DelegateCapturesFirstArgument;//TODO: IsExtensionMethodStyle(new CsInvocationExpression { entity = me, expression = node }); JsExpression firstPrm = null; if (isExtensionMethodStyle) { firstPrm = (JsExpression)Visit(res.TargetResult); } var node2 = SkJs.EntityToMember(me); JsExpression node3; JsExpression instanceContext = null; if (me.IsStatic || res.TargetResult == null) //getting ThisResolveResult even on static methods, getting TargetResult=null when MethodGroupResolveResult when using delegates { node3 = node2; } else { instanceContext = VisitExpression(res.TargetResult); node3 = instanceContext.Member(node2); } if (info != null && (instanceContext != null || firstPrm != null)) { if (info.ConversionTargetType != null && !UseNativeFunctions(info.ConversionTargetType))//delegate type { var parentMethod = info.Nodes.FirstOrDefault().GetCurrentMethod(); if (parentMethod == null || !Sk.ForceDelegatesAsNativeFunctions(parentMethod)) { if (parentMethod == null) { Log.Warn(info.Nodes.FirstOrDefault(), "GetParentMethod() returned null"); } var func = (JsExpression)node2; if (instanceContext != null) { node3 = CreateJsDelegate(instanceContext, func); } else if (firstPrm != null) { node3 = CreateJsExtensionDelegate(firstPrm, func); } } } } // 其实以下的处理,也可以改代码,改成 Lambda 写法即可 // 这样子引用的并不是同一个函数,可能会造成内存泄露 if (res.TypeArguments.Count > 0 && info.Conversion.IsImplicit && me is SpecializedMethod) { var delegateFunc = node3 as JsInvocationExpression; var sme = (SpecializedMethod)me; var pars = sme.TypeArguments.Select(type => SkJs.EntityTypeRefToMember(type, false)).ToList(); pars.AddRange(sme.Parameters.Select(t => new JsCodeExpression { Code = JsIdentifier(t.Name), })); var body = delegateFunc == null?node3.Invoke(pars.ToArray()) : delegateFunc.Arguments[1].Invoke(pars.ToArray()); var func = new JsFunction() { Parameters = sme.Parameters.Select(t => JsIdentifier(t.Name)).ToList(), }; JsStatement st; if (sme.ReturnType.IsVoid()) { st = new JsExpressionStatement { Expression = body }; } else { st = new JsReturnStatement { Expression = body }; } func.Block = new JsBlock { Statements = new List <JsStatement> { st } }; if (delegateFunc == null) { node3 = func; } else { delegateFunc.Arguments[1] = func; } } return(node3); }