/// <summary> /// 分析绑定方法 /// </summary> /// <param name="invocation"></param> /// <param name="components"></param> protected virtual void AnalysisBindingEvents(InvocationExpression invocation, List <ComponentItem> components) { var component = components.Find(x => invocation.Arguments.Count > 1 && invocation.Arguments.First().ToString().Contains("m_" + x.name)); if (component != null) { var sourceName = GenCodeUtil.FromSourceKey(invocation.Arguments.ToArray()[1].ToString()); var info = component.eventItems.Find(x => x.bindingSource == sourceName); var arg0 = invocation.Arguments.First().ToString(); var targetName = arg0.Substring(arg0.IndexOf(".") + 1); Type infoType = GetTypeClamp(component.componentType, targetName); if (info == null) { info = new BindingEvent(); info.bindingSource = sourceName; info.bindingTarget = targetName; info.bindingTargetType.Update(infoType); component.eventItems.Add(info); } info.bindingTargetType.Update(infoType); if (invocation.Arguments.Count() > 2) { info.type = BindingType.WithTarget;//3个参数 } else { info.type = BindingType.Normal;//2个参数 } } }
/// <summary> /// 分析绑定member /// </summary> /// <param name="invocation"></param> /// <param name="components"></param> protected virtual void AnalysisBindingMembers(InvocationExpression invocation, List <ComponentItem> components) { var component = components.Find(x => invocation.Arguments.Count > 1 && invocation.Arguments.First().ToString().Contains(string.Format("m_{0}.", x.name))); if (component != null) { var sourceName = GenCodeUtil.FromSourceKey(invocation.Arguments.ToArray()[1].ToString()); var info = component.viewItems.Find(x => x.bindingSource == sourceName); var isMethod = false; var targetName = AnalysisTargetFromLamdaArgument(invocation.Arguments.First().ToString(), out isMethod); //UnityEngine.Debug.Log("解析出字段:" + targetName); //UnityEngine.Debug.Log("目标名:" + sourceName); if (string.IsNullOrEmpty(targetName)) { UnityEngine.Debug.Assert(!string.IsNullOrEmpty(targetName), "annalysis err:" + invocation.Arguments.First().ToString()); return; } var type = GetTypeClamp(component.componentType, targetName); //UnityEngine.Debug.Log("解析出类型:" + type); if (info == null) { info = new BindingShow(); info.bindingSource = sourceName; info.bindingTarget = targetName; info.isMethod = isMethod; component.viewItems.Add(info); } info.bindingTargetType.Update(type); } }
/// <summary> /// Binding关联 /// </summary> /// <returns></returns> public virtual void CompleteCode(ComponentItem component, bool bindingAble) { foreach (var item in component.viewItems) { GenCodeUtil.CompleteKeyField(item.bindingSource, classNode); BindingMemberInvocations(component.name, item); } foreach (var item in component.eventItems) { GenCodeUtil.CompleteKeyField(item.bindingSource, classNode); switch (item.type) { case BindingType.NoBinding: LocalEventInvocations(component.name, item, bindingAble); break; case BindingType.Normal: case BindingType.WithTarget: BindingEventInvocations(component.name, component.componentType, item); break; default: break; } } }
/// <summary> /// 更新View 和 ViewModel的脚本 /// </summary> /// <param name="go"></param> /// <param name="components"></param> /// <param name="rule"></param> public static void UpdateScripts(GameObject go, List <ComponentItem> components, GenCodeRule rule) { rule.onGenerated = (viewScript) => { if (viewScript is PanelBase) { var viewScriptPath = AssetDatabase.GetAssetPath(viewScript); //!!!ViewModelScript需要放置到ViewScript下 var vmScriptTempPath = viewScriptPath.Replace(".cs", "_ViewModel.cs"); var viewModelScript = AssetDatabase.LoadAssetAtPath <MonoScript>(vmScriptTempPath); var viewModel = (viewScript as PanelBase).ViewModel; if (viewModelScript != null) { GenCodeUtil.UpdateViewModelScript(viewModelScript, components); } else { var vscript = MonoScript.FromMonoBehaviour(viewScript as PanelBase); string scriptPath = null; if (vscript.name == go.name) { scriptPath = AssetDatabase.GetAssetPath(vscript).Replace(".cs", "_ViewModel.cs"); } else { scriptPath = AssetDatabase.GetAssetPath(go).Replace(".prefab", "_ViewModel.cs"); } CreateNewViewModelScript(go.name + "_ViewModel", scriptPath, components); } } }; GenCodeUtil.CreateViewScript(go, components, rule); }
/// <summary> /// 分析代码中的绑定信息 /// </summary> /// <param name="invocation"></param> /// <param name="components"></param> private static void AnalysisBindingMembers(string invocation, ComponentItem[] components) { var arguments = invocation.Replace(" ", "").Split(','); bool isMethod; var lamdaArgs = AnalysisTargetFromLamdaArgument(arguments[0], out isMethod); for (int i = 0; i < components.Length; i++) { var component = components[i]; var sourceName = arguments[1].Replace(keyword_address, ""); var targetName = lamdaArgs[2]; if (component.name == lamdaArgs[1]) { BindingShow info = component.viewItems.Find(x => x.bindingTarget == targetName); if (info == null) { info = new BindingShow(); component.viewItems.Add(info); } info.bindingSource = sourceName; info.bindingTarget = targetName; info.isMethod = isMethod; var type = GenCodeUtil.GetTypeClamp(component.componentType, targetName); info.bindingTargetType.Update(type); } } }
/// <summary> /// 远端关联事件 /// </summary> /// <param name="name"></param> /// <param name="bindingInfo"></param> protected virtual void BindingEventInvocations(string name, Type componentType, BindingEvent bindingInfo) { var invocations = PropBindingsNode.Body.Descendants.OfType <InvocationExpression>(); var arg0_name = "m_" + name + "." + bindingInfo.bindingTarget; //绑定目标 var arg1_name = GenCodeUtil.GetSourceKeyWord(bindingInfo.bindingSource); //绑定源 var may_invocations = invocations.Where( x => x.Target.ToString().Contains("Binder") && x.Arguments.Count > 0 && x.Arguments.First().ToString() == arg0_name && x.Arguments.ToArray().Length > 1 && x.Arguments.ToArray()[1].ToString() == arg1_name); InvocationExpression invocation = null; if (may_invocations != null) { //两个参数 if (bindingInfo.type == BindingType.Normal) { invocation = may_invocations.Where(x => x.Arguments.Count() == 2).FirstOrDefault(); } //三个参数 else if (bindingInfo.type == BindingType.WithTarget) { invocation = may_invocations.Where(x => x.Arguments.ToArray().Length > 2 && x.Arguments.ToArray()[2].ToString() == "m_" + name).FirstOrDefault(); } } if (invocation == null) { var methodName = "RegistEvent"; UnityEngine.Debug.Assert(bindingInfo.bindingTargetType.type != null, bindingInfo.bindingSource + ";" + bindingInfo.bindingTarget + " type Null"); ///从UnityEvent和UnityEvent<T>派生 if (bindingInfo.bindingTargetType.type.BaseType.IsGenericType) { var arguments = bindingInfo.bindingTargetType.type.BaseType.GetGenericArguments().Select(x => x.FullName).ToList(); if (bindingInfo.type == BindingType.WithTarget) { arguments.Add(componentType.FullName); } methodName = "RegistEvent<" + string.Join(",", arguments.ToArray()) + ">"; } if (!string.IsNullOrEmpty(methodName)) { invocation = new InvocationExpression(); invocation.Target = new MemberReferenceExpression(new IdentifierExpression("Binder"), methodName, new AstType[0]); invocation.Arguments.Add(new IdentifierExpression(arg0_name)); invocation.Arguments.Add(new IdentifierExpression(GenCodeUtil.GetSourceKeyWord(bindingInfo.bindingSource))); if (bindingInfo.type == BindingType.WithTarget) { invocation.Arguments.Add(new IdentifierExpression("m_" + name)); } PropBindingsNode.Body.Add(invocation); } } }
/// <summary> /// 远端member关联 /// </summary> protected virtual void BindingMemberInvocations(string name, BindingShow bindingInfo) { var invocations = PropBindingsNode.Body.Descendants.OfType <InvocationExpression>(); var arg0_name = "m_" + name + "." + bindingInfo.bindingTarget; var arg0 = arg0_name; //UnityEngine.Debug.Log(bindingInfo.bindingTargetType.type); //UnityEngine.Debug.Log(bindingInfo.isMethod); if (!bindingInfo.isMethod) { arg0 = string.Format("x=>{0}=x", arg0_name); } //UnityEngine.Debug.Log(bindingInfo.bindingTarget); //UnityEngine.Debug.Log(bindingInfo.bindingTargetType.type); var arg1 = GenCodeUtil.GetSourceKeyWord(bindingInfo.bindingSource); var invocation = invocations.Where( x => x.Target.ToString().Contains("Binder") && x.Arguments.Count > 0 && x.Arguments.First().ToString().Replace(" ", "") == arg0 && x.Arguments.ToArray()[1].ToString() == arg1).FirstOrDefault(); if (invocation == null) { string methodName = ""; UnityEngine.Debug.Assert(bindingInfo.bindingTargetType.type != null, name + ":" + bindingInfo.bindingSource + " type Null!"); if (!bindingInfo.bindingTargetType.type.IsGenericType) { var typeName = bindingInfo.bindingTargetType.typeName; methodName = string.Format("RegistValueChange<{0}>", typeName); } else { var type = bindingInfo.bindingTargetType.type; var baseName = type.Name.Remove(type.Name.IndexOf("`")); var arguments = type.GetGenericArguments(); baseName += "<"; baseName += string.Join(",", Array.ConvertAll <Type, string>(arguments, x => x.FullName)); baseName += ">"; methodName = string.Format("RegistValueChange<{0}>", baseName); } if (!string.IsNullOrEmpty(methodName)) { invocation = new InvocationExpression(); invocation.Target = new MemberReferenceExpression(new IdentifierExpression("Binder"), methodName, new AstType[0]); invocation.Arguments.Add(new IdentifierExpression(arg0)); invocation.Arguments.Add(new IdentifierExpression(GenCodeUtil.GetSourceKeyWord(bindingInfo.bindingSource))); PropBindingsNode.Body.Add(invocation); } } }
/// <summary> /// 更新View 和 ViewModel的脚本 /// </summary> /// <param name="go"></param> /// <param name="components"></param> /// <param name="rule"></param> public static void UpdateScripts(GameObject go, List <ComponentItem> components, GenCodeRule rule) { rule.onGenerated = (viewScript) => { if (viewScript is PanelBase) { var viewModel = (viewScript as PanelBase).ViewModel; if (viewModel) { GenCodeUtil.UpdateViewModelScript(viewModel, components); } } }; GenCodeUtil.CreateViewScript(go, components, rule); }
/// <summary> /// ViewModel部分代码生成 /// </summary> /// <param name="protocals"></param> /// <param name="types"></param> /// <param name="sb"></param> private void CreateViewModelScript(List <string> protocals, List <Type> types, StringBuilder sb) { sb.Append("\t\t"); sb.AppendLine("/// <summary>"); sb.Append("\t\t"); sb.AppendLine("/// 显示模型模板"); sb.Append("\t\t"); sb.AppendLine("/// <summary>"); sb.Append("\t\t"); sb.AppendLine("public class LogicBase : BridgeUI.Binding.ViewModel"); sb.Append("\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t"); sb.AppendLine("#region BindablePropertys"); for (int i = 0; i < protocals.Count; i++) { var protocal = protocals[i]; var typeName = GenCodeUtil.TypeStringName(types[i]); sb.Append("\t\t\t"); sb.AppendFormat("protected BindableProperty<{0}> m_{1};", typeName, protocal); sb.AppendLine(); } sb.Append("\t\t\t"); sb.AppendLine("#endregion BindablePropertys"); sb.AppendLine(); sb.Append("\t\t\t"); sb.AppendLine("#region Propertys"); for (int i = 0; i < protocals.Count; i++) { var protocal = protocals[i]; var typeName = GenCodeUtil.TypeStringName(types[i]); sb.Append("\t\t\t"); sb.AppendFormat("public {0} {1}", typeName, protocal); sb.AppendLine(); sb.Append("\t\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t\t"); sb.AppendLine("get"); sb.Append("\t\t\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t\t\t"); sb.AppendFormat("if(m_{0} == null)", protocal); sb.AppendLine(); sb.Append("\t\t\t\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t\t\t\t"); sb.AppendFormat("m_{0} = GetBindableProperty<{1}>({2});", protocal, typeName, GetKeyword(protocal)); sb.AppendLine(); sb.Append("\t\t\t\t\t"); sb.AppendLine("}"); sb.Append("\t\t\t\t\t"); sb.AppendFormat("return m_{0};", protocal); sb.AppendLine(); sb.Append("\t\t\t\t"); sb.AppendLine("}"); sb.Append("\t\t\t\t"); sb.AppendLine("set"); sb.Append("\t\t\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t\t\t"); sb.AppendFormat("if(m_{0} == null)", protocal); sb.AppendLine(); sb.Append("\t\t\t\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t\t\t\t"); sb.AppendFormat("m_{0} = GetBindableProperty<{1}>({2});", protocal, typeName, GetKeyword(protocal)); sb.AppendLine(); sb.Append("\t\t\t\t\t"); sb.AppendLine("}"); sb.Append("\t\t\t\t\t"); sb.AppendFormat("m_{0}.Value = value;", protocal); sb.AppendLine(); sb.Append("\t\t\t\t"); sb.AppendLine("}"); sb.Append("\t\t\t"); sb.AppendLine("}"); } sb.Append("\t\t\t"); sb.AppendLine("#endregion Propertys"); sb.Append("\t\t"); sb.AppendLine("}"); }
/// <summary> /// 创建代码 /// </summary> /// <param name="go"></param> /// <param name="components"></param> /// <param name="rule"></param> public static void CreateViewScript(GameObject go, List <ComponentItem> components, GenCodeRule rule) { Action <UICoder> onLoad = (uiCoder) => { var baseType = GenCodeUtil.supportBaseTypes[rule.baseTypeIndex]; var needAdd = FilterExisField(baseType, components); var tree = uiCoder.tree; var className = uiCoder.className; var classNode = tree.Descendants.OfType <TypeDeclaration>().Where(x => x.Name == className).First(); CreateMemberFields(classNode, needAdd); BindingInfoMethods(classNode, needAdd, rule); SortClassMembers(classNode); var prefabPath = AssetDatabase.GetAssetPath(go); var folder = prefabPath.Remove(prefabPath.LastIndexOf("/")); var scriptPath = string.Format("{0}/{1}.cs", folder, uiCoder.className); var scriptValue = uiCoder.Compile(); System.IO.File.WriteAllText(scriptPath, scriptValue, System.Text.Encoding.UTF8); AssetDatabase.Refresh(); EditorApplication.delayCall += () => { var type = typeof(BridgeUI.PanelBase).Assembly.GetType(className); if (type != null) { var script = go.GetComponent(type); if (script == null) { go.AddComponent(type); } if (rule.onGenerated != null) { rule.onGenerated.Invoke(script); } EditorApplication.update = null; } AssetDatabase.Refresh(); }; }; GenCodeUtil.LoadViewScriptCoder(go, rule, onLoad); }
/// <summary> /// 更新View 和 ViewModel的脚本 /// </summary> /// <param name="go"></param> /// <param name="components"></param> /// <param name="rule"></param> public static void UpdateScripts(GameObject go, List <ComponentItem> components, GenCodeRule rule) { rule.onGenerated = (viewScript) => { if (viewScript is PanelBase) { var viewModel = (viewScript as PanelBase).ViewModel; if (viewModel is Binding.ViewModel && viewModel.GetType() != typeof(Binding.ViewModel)) { GenCodeUtil.UpdateViewModelScript(viewModel as Binding.ViewModel, components); } else if (viewModel is Binding.ViewModelContainer) { GenCodeUtil.UpdateViewModelScript((viewModel as Binding.ViewModelContainer).instence, components); } } }; GenCodeUtil.CreateViewScript(go, components, rule); }
private void AnalysisBindingMembers(string componentName, string targetName, string sourceName, bool isMethod, ComponentItem[] components) { for (int i = 0; i < components.Length; i++) { var component = components[i]; if (component.name == componentName) { BindingShow info = component.viewItems.Find(x => x.bindingTarget == targetName); if (info == null) { info = new BindingShow(); component.viewItems.Add(info); } info.bindingSource = sourceName; info.bindingTarget = targetName; info.isMethod = isMethod; var type = GenCodeUtil.GetTypeClamp(component.componentType, targetName); info.bindingTargetType.Update(type); } } }
public override void AnalysisBinding(GameObject gameObject, ComponentItem[] componentItems) { var scriptPath = GenCodeUtil.InitScriptPath(gameObject, "_Internal"); if (System.IO.File.Exists(scriptPath)) { var script = System.IO.File.ReadAllText(scriptPath, System.Text.Encoding.UTF8); if (componentItems != null) { script = script.Replace(" ", ""); //解析componentItem AnalysisBindingMembers(script, componentItems); AnalysisBindingEvents(script, componentItems); } } else { Debug.Assert(System.IO.File.Exists(scriptPath), "未找到:" + scriptPath); } }
public override void AnalysisBinding(GameObject gameObject, ComponentItem[] componentItems) { var scriptPath = GenCodeUtil.InitScriptPath(gameObject, "_Internal"); if (System.IO.File.Exists(scriptPath)) { var script = System.IO.File.ReadAllText(scriptPath, System.Text.Encoding.UTF8); if (componentItems != null) { //解析componentItem var bindingMembers = new List <string>(); var bindingEvents = new List <string>(); GetInvocations(script, ref bindingMembers, ref bindingEvents); bindingMembers.ForEach(x => AnalysisBindingMembers(x, componentItems)); bindingEvents.ForEach(x => AnalysisBindingEvents(x, componentItems)); } } else { Debug.Assert(System.IO.File.Exists(scriptPath), "未找到:" + scriptPath); } }
/// <summary> /// 分析本地方法 /// </summary> /// <param name="invocation"></param> /// <param name="components"></param> protected virtual void AnalysisLoaclInvocation(InvocationExpression invocation, List <ComponentItem> components) { var component = components.Find(x => invocation.Target.ToString().Contains("m_" + x.name)); if (component != null) { string bindingSource = GenCodeUtil.FromSourceKey(invocation.Arguments.First().ToString()); var info = component.eventItems.Find(x => invocation.Target.ToString().Contains("m_" + component.name + "." + x.bindingTarget) && x.type == BindingType.NoBinding && x.bindingSource == bindingSource); if (info == null) { var express = invocation.Target as MemberReferenceExpression; var target = (express.Target as MemberReferenceExpression).MemberNameToken.Name; Type infoType = GetTypeClamp(component.componentType, target); info = new BindingEvent(); info.type = BindingType.NoBinding; info.bindingSource = bindingSource; info.bindingTarget = target; info.bindingTargetType.Update(infoType); component.eventItems.Add(info); } } }
private void AnalysisBindingEvents(string componentName, string targetName, string sourceName, ComponentItem[] components) { for (int i = 0; i < components.Length; i++) { var component = components[i]; if (component.name == componentName) { Type infoType = GenCodeUtil.GetTypeClamp(component.componentType, targetName); var info = component.eventItems.Find(x => x.bindingSource == sourceName); if (info == null) { info = new BindingEvent(); component.eventItems.Add(info); } info.bindingSource = sourceName; info.bindingTarget = targetName; info.bindingTargetType.Update(infoType); info.type = BindingType.Simple; } } }
/// <summary> /// 事件绑定信息解析 /// </summary> /// <param name="invocation"></param> /// <param name="components"></param> private static void AnalysisBindingEvents(string invocation, ComponentItem[] components) { var arguments = invocation.Replace(" ", "").Split(','); var arg0s = arguments[0].Split('.'); for (int i = 0; i < components.Length; i++) { var component = components[i]; var targetName = arg0s[2]; var sourceName = arguments[1].Replace(keyword_address, ""); if (component.name == arg0s[1]) { Type infoType = GenCodeUtil.GetTypeClamp(component.componentType, targetName); var info = component.eventItems.Find(x => x.bindingSource == sourceName); if (info == null) { info = new BindingEvent(); component.eventItems.Add(info); } info.bindingSource = sourceName; info.bindingTarget = targetName; info.bindingTargetType.Update(infoType); if (arguments.Length > 2) { info.type = BindingType.Full;//3个参数 } else { info.type = BindingType.Simple;//2个参数 } } } }
/// <summary> /// View部分代码生成 /// </summary> /// <param name="sb"></param> private void CreateViewScript(StringBuilder sb) { var uicontrols = componentItems.Where(x => typeof(IUIControl).IsAssignableFrom(x.componentType)).ToArray(); sb.Append("\t\t"); sb.AppendLine("/// <summary>"); sb.Append("\t\t"); sb.AppendLine("/// 代码绑定"); sb.Append("\t\t"); sb.AppendLine("/// </summary>"); sb.Append("\t\t"); sb.AppendLine("protected override void OnBinding(UnityEngine.GameObject target)"); sb.Append("\t\t"); sb.AppendLine("{"); sb.Append("\t\t\t"); sb.AppendLine("base.OnBinding(target);"); sb.Append("\t\t\t"); sb.AppendFormat("var binding = target.GetComponent<{0}>();\r\n", refClassName); sb.Append("\t\t\t"); sb.AppendLine("if (binding != null)"); sb.Append("\t\t\t"); sb.AppendLine("{"); for (int i = 0; i < componentItems.Length; i++) { var componentItem = componentItems[i]; var viewBindings = componentItem.viewItems; for (int j = 0; j < viewBindings.Count; j++) { var viewItem = viewBindings[j]; sb.Append("\t\t\t\t"); sb.AppendFormat("Binder.RegistValueChange<{0}>(x => binding.{1}.{2} = x, {3});", GenCodeUtil.TypeStringName(viewItem.bindingTargetType.type), componentItem.name, viewItem.bindingTarget, GetKeyword(viewItem.bindingSource)); sb.AppendLine(); } var eventBindings = componentItem.eventItems; for (int j = 0; j < eventBindings.Count; j++) { var eventItem = eventBindings[j]; sb.Append("\t\t\t\t"); switch (eventItem.type) { case BindingType.Simple: sb.AppendFormat("Binder.RegistEvent(binding.{0}.{1}, {2});", componentItem.name, eventItem.bindingTarget, GetKeyword(eventItem.bindingSource)); break; case BindingType.Full: sb.AppendFormat("Binder.RegistEvent(binding.{0}.{1}, {2},binding.{3});", componentItem.name, eventItem.bindingTarget, GetKeyword(eventItem.bindingSource), componentItem.name); break; default: break; } sb.AppendLine(); } } if (innerFields != null) { for (int i = 0; i < innerFields.Length; i++) { var field = innerFields[i]; if (!typeof(UnityEngine.Object).IsAssignableFrom(field.FieldType)) { sb.Append("\t\t\t\t"); sb.AppendFormat("Binder.SetValue(binding.{0}, {1});", field.Name, GetKeyword(field.Name)); sb.AppendLine(); } } } if (uicontrols != null && uicontrols.Length > 0) { for (int i = 0; i < uicontrols.Length; i++) { var item = uicontrols[i]; sb.Append("\t\t\t\t"); sb.AppendFormat("RegistUIControl(binding.{0});", item.name); sb.AppendLine(); } } sb.Append("\t\t\t"); sb.AppendLine("}"); sb.Append("\t\t"); sb.AppendLine("}"); }
/// <summary> /// 本地事件关联 /// </summary> protected virtual void LocalEventInvocations(string name, BindingEvent bindingInfo, bool bindingAble) { var node = bindingAble ? InitComponentsNode : AwakeNode; var invocations = node.Body.Descendants.OfType <InvocationExpression>(); var targetName = "m_" + name; var invocation = invocations.Where(x => x.Target.ToString().Contains(targetName) && x.Arguments.FirstOrDefault().ToString() == GenCodeUtil.GetSourceKeyWord(bindingInfo.bindingSource)).FirstOrDefault(); var eventName = bindingInfo.bindingTarget;//如onClick if (invocation == null && !string.IsNullOrEmpty(eventName) && !string.IsNullOrEmpty(bindingInfo.bindingSource)) { invocation = new InvocationExpression(); invocation.Target = new MemberReferenceExpression(new MemberReferenceExpression(new IdentifierExpression("m_" + name), eventName, new AstType[0]), "AddListener", new AstType[0]); invocation.Arguments.Add(new IdentifierExpression(bindingInfo.bindingSource)); node.Body.Add(invocation); CompleteMethod(bindingInfo); } }