private void GenerateSignals(IDLInterface idlIntf, string nsName , CodeTypeReference typerefDbusInterface , CodeTypeReference typerefDbusMarshal , CodeTypeReference typerefWCFCallbackInterface , CodeTypeDeclaration typeProxy) { #region list of callbacks // Callbacks field. // * LinkedList<I<interface>Callback> callbacks = null; CodeTypeReference typerefCallbacksLinkedList = new CodeTypeReference(typeof(LinkedList <>)); typerefCallbacksLinkedList.TypeArguments.Add(typerefWCFCallbackInterface); CodeMemberField fieldCallbacks = new CodeMemberField(typerefCallbacksLinkedList, callbacks); fieldCallbacks.InitExpression = new CodePrimitiveExpression(null); typeProxy.Members.Add(fieldCallbacks); #endregion #region Method: OnCallBackClosing // Write: // private void OnCallbackClosing(object sender, System.EventArgs e) // { // RemoveCallback(sender, this.callbacks); // } CodeMemberMethod methodOnCallbackClosing = new CodeMemberMethod(); methodOnCallbackClosing.Attributes = MemberAttributes.Private; methodOnCallbackClosing.Name = "OnCallbackClosing"; CodeParameterDeclarationExpression paramdeclSender = new CodeParameterDeclarationExpression(typerefObject, "sender"); CodeArgumentReferenceExpression argrefSender = new CodeArgumentReferenceExpression(paramdeclSender.Name); CodeParameterDeclarationExpression paramdeclEventArgs = new CodeParameterDeclarationExpression(typeof(System.EventArgs), "e"); CodeArgumentReferenceExpression argrefEventArgs = new CodeArgumentReferenceExpression(paramdeclEventArgs.Name); methodOnCallbackClosing.Parameters.Add(paramdeclSender); methodOnCallbackClosing.Parameters.Add(paramdeclEventArgs); methodOnCallbackClosing.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(null, RemoveCallback, argrefSender, fieldrefCallbacks))); typeProxy.Members.Add(methodOnCallbackClosing); #endregion #region Method: AddCallBack // AddCallback(). // * private void AddCallback(I<interface>Callback callback) CodeParameterDeclarationExpression paramdeclCallback = new CodeParameterDeclarationExpression(typerefWCFCallbackInterface, CodeBuilderCommon.callback); CodeArgumentReferenceExpression argrefCallback = new CodeArgumentReferenceExpression(paramdeclCallback.Name); CodeMemberMethod methodAddCallback = new CodeMemberMethod(); methodAddCallback.Attributes = MemberAttributes.Private; methodAddCallback.Name = AddCallback; methodAddCallback.Parameters.Add(paramdeclCallback); CodeArrayCreateExpression arraycreatexprCallbacks = new CodeArrayCreateExpression(typerefWCFCallbackInterface); arraycreatexprCallbacks.Initializers.Add(argrefCallback); CodeVariableReferenceExpression varrefRegisterComms = new CodeVariableReferenceExpression("registerComms"); // * bool registerComms = true; methodAddCallback.Statements.Add(new CodeVariableDeclarationStatement(typeof(bool) , varrefRegisterComms.VariableName , new CodePrimitiveExpression(true))); CodeTypeReference typerefCallbackEnumerator = new CodeTypeReference(typeof(System.Collections.Generic.IEnumerator <>)); typerefCallbackEnumerator.TypeArguments.Add(typerefWCFCallbackInterface); CodeVariableReferenceExpression varrefCallbackEnumerator = new CodeVariableReferenceExpression(callbackEnumerator); CodeVariableDeclarationStatement vardeclCallbackEnumerator = new CodeVariableDeclarationStatement(typerefCallbackEnumerator, varrefCallbackEnumerator.VariableName, new CodeMethodInvokeExpression(fieldrefCallbacks, "GetEnumerator")); CodePropertyReferenceExpression proprefCallbackEnumeratorCurrent = new CodePropertyReferenceExpression(varrefCallbackEnumerator, "Current"); CodeMethodInvokeExpression invokeCallbackEnumeratorMoveNext = new CodeMethodInvokeExpression(varrefCallbackEnumerator, "MoveNext"); CodeVariableDeclarationStatement vardeclCallbackEnumeratorMoveNext = new CodeVariableDeclarationStatement(typeof(bool), callbackEnumeratorMoveNext, invokeCallbackEnumeratorMoveNext); CodeVariableReferenceExpression varrefCallbackEnumeratorMoveNext = new CodeVariableReferenceExpression(vardeclCallbackEnumeratorMoveNext.Name); CodeAssignStatement assignCallbackEnumeratorMoveNext = new CodeAssignStatement(varrefCallbackEnumeratorMoveNext, invokeCallbackEnumeratorMoveNext); methodAddCallback.Statements.Add( // * if (this.callbacks == null) new CodeConditionStatement(new CodeBinaryOperatorExpression(fieldrefCallbacks , CodeBinaryOperatorType.IdentityEquality , new CodePrimitiveExpression(null)) , new CodeStatement[] { // * this.callbacks = new LinkedList<I<interface>Callback>(new I<interface>Callback[] { callback }); new CodeAssignStatement(fieldrefCallbacks , new CodeObjectCreateExpression(typerefCallbacksLinkedList , arraycreatexprCallbacks) ) } // * else , new CodeStatement[] { // * IEnumerator<[callback_interface]> callbacksEnumerator = this.callbacks.GetEnumerator(); vardeclCallbackEnumerator // * for (bool callbackEnumeratorMoveNext = callbackEnumerator.MoveNext(); callbackEnumeratorMoveNext; callbackEnumeratorMoveNext = callbackEnumerator.MoveNext()) // * { , new CodeIterationStatement(vardeclCallbackEnumeratorMoveNext , new CodeBinaryOperatorExpression(varrefCallbackEnumeratorMoveNext , CodeBinaryOperatorType.BooleanAnd , varrefRegisterComms) , assignCallbackEnumeratorMoveNext // * if (callbacksEnumerator.Current.Equals(callback)) // * { , new CodeConditionStatement(new CodeMethodInvokeExpression(proprefCallbackEnumeratorCurrent , "Equals" , argrefCallback) , new CodeStatement[] // True { // * registerComms = false; new CodeAssignStatement(varrefRegisterComms, new CodePrimitiveExpression(false)) } ) ) // * if (registerComms) , new CodeConditionStatement(varrefRegisterComms // * this.callbacks.AddLast(callback); , new CodeExpressionStatement(new CodeMethodInvokeExpression(fieldrefCallbacks , "AddLast" , argrefCallback)) ) } )); // * System.ServiceModel.ICommunicationObject commsCallback = callback as System.ServiceModel.ICommunicationObject; // * if (registerComms && (typeof(System.ServiceModel.ICommunicationObject).IsInstanceOfType(callback) != false)) // * { // * commsCallback.Closing += this.OnCallbackClosing; // * } CodeTypeReference typerefICommunicationObject = new CodeTypeReference(typeof(System.ServiceModel.ICommunicationObject)); CodeVariableDeclarationStatement vardeclCallbackAsComms = new CodeVariableDeclarationStatement(typerefICommunicationObject , "commsCallback" , new CodeCastExpression(typerefICommunicationObject, argrefCallback) ); CodeVariableReferenceExpression varrefCallbackAsComms = new CodeVariableReferenceExpression(vardeclCallbackAsComms.Name); methodAddCallback.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression( varrefRegisterComms , CodeBinaryOperatorType.BooleanAnd , new CodeBinaryOperatorExpression( new CodeMethodInvokeExpression(new CodeTypeOfExpression(typerefICommunicationObject), "IsInstanceOfType", argrefCallback) , CodeBinaryOperatorType.IdentityInequality , new CodePrimitiveExpression(false) ) ) , vardeclCallbackAsComms , new CodeAttachEventStatement(varrefCallbackAsComms, "Closing", new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), methodOnCallbackClosing.Name)) )); typeProxy.Members.Add(methodAddCallback); #endregion #region Method: RemoveCallBack // RemoveCallback(). /// * static private void RemoveCallback<T>(object callback, LinkedList<T> callbacks) /// * where T: class /// * { CodeMemberMethod methodRemoveCallback = new CodeMemberMethod(); methodRemoveCallback.Attributes = MemberAttributes.Static | MemberAttributes.Private; methodRemoveCallback.Name = RemoveCallback; CodeTypeParameter typeparamCallback = new CodeTypeParameter("TCallback"); CodeTypeReference typerefCallbackParam = new CodeTypeReference(typeparamCallback.Name); CodeParameterDeclarationExpression paramdeclRemoveCallback = new CodeParameterDeclarationExpression(typerefObject, CodeBuilderCommon.callback); CodeTypeReference typerefLinkedListRemoveCallback = new CodeTypeReference(typeof(System.Collections.Generic.LinkedList <>)); typerefLinkedListRemoveCallback.TypeArguments.Add(typerefCallbackParam); CodeTypeReference typerefLinkedListNodeRemoveCallback = new CodeTypeReference(typeof(System.Collections.Generic.LinkedListNode <>)); typerefLinkedListNodeRemoveCallback.TypeArguments.Add(typerefCallbackParam); CodeParameterDeclarationExpression paramdeclRemoveCallbacks = new CodeParameterDeclarationExpression(typerefLinkedListRemoveCallback, callbacks); CodeArgumentReferenceExpression argrefCallbacks = new CodeArgumentReferenceExpression(paramdeclRemoveCallbacks.Name); typeparamCallback.Constraints.Add(new CodeTypeReference(" class")); // Space before "class" bloody important, stupid CodeDOM and CSharp. methodRemoveCallback.TypeParameters.Add(typeparamCallback); methodRemoveCallback.Parameters.Add(paramdeclRemoveCallback); methodRemoveCallback.Parameters.Add(paramdeclRemoveCallbacks); CodeVariableDeclarationStatement vardeclIteratorNode = new CodeVariableDeclarationStatement( typerefLinkedListNodeRemoveCallback, "iteratorNode" , new CodePropertyReferenceExpression(argrefCallbacks, "First") ); CodeVariableReferenceExpression varrefIteratorNode = new CodeVariableReferenceExpression(vardeclIteratorNode.Name); CodeVariableDeclarationStatement vardeclRemoveNode = new CodeVariableDeclarationStatement( typerefLinkedListNodeRemoveCallback, "removeNode" , varrefIteratorNode ); CodeVariableReferenceExpression varrefRemoveNode = new CodeVariableReferenceExpression(vardeclRemoveNode.Name); CodeAssignStatement assignIteratorNode = new CodeAssignStatement(varrefIteratorNode, new CodePropertyReferenceExpression(varrefIteratorNode, "Next")); // * for (LinkedListNode<string> n = l.First; n != null; ) // * { methodRemoveCallback.Statements.Add(new CodeIterationStatement(vardeclIteratorNode , new CodeBinaryOperatorExpression(varrefIteratorNode , CodeBinaryOperatorType.IdentityInequality , new CodePrimitiveExpression(null)) , new CodeSnippetStatement(string.Empty) // Don't increment // * if (iteratorNode.Value == callback) // * { , new CodeConditionStatement( new CodeBinaryOperatorExpression(new CodePropertyReferenceExpression(varrefIteratorNode, "Value") , CodeBinaryOperatorType.IdentityEquality , argrefCallback) , new CodeStatement[] // True { // * LinkedListNode<string> removeNode = iteratorNode; vardeclRemoveNode // * iteratorNode = iteratorNode.Next; , assignIteratorNode // * l.Remove(removeNode); , new CodeExpressionStatement(new CodeMethodInvokeExpression(argrefCallbacks, "Remove", varrefRemoveNode)) // * } } // * else // * { , new CodeStatement[] // False { // * iteratorNode = iteratorNode.Next; assignIteratorNode // * } } // * } // * } ))); typeProxy.Members.Add(methodRemoveCallback); #endregion foreach (IDLSignal idlSignal in idlIntf.Signals) { #region Write method which will call every registered // Add private event handler function which delegates to callback interfaces. // * private void On<signal>(object sender, <signal_interface_ns>.<signal>Args e) string signalArgsName = CodeBuilderCommon.GetSignalEventTypeName(idlSignal.Name); string scopedSignalArgsName = CodeBuilderCommon.GetScopedName(nsName, signalArgsName); string signalEventMethodName = CodeBuilderCommon.GetSignalCallbackMethodName(idlSignal.Name); CodeTypeReference typerefSignalEventArgs = new CodeTypeReference(scopedSignalArgsName); CodeParameterDeclarationExpression paramdeclSignalEventArgs = new CodeParameterDeclarationExpression(typerefSignalEventArgs, eventArgsParamName); CodeArgumentReferenceExpression argrefSignalEventArgs = new CodeArgumentReferenceExpression(paramdeclSignalEventArgs.Name); CodeMemberMethod methodOnSignal = new CodeMemberMethod(); methodOnSignal.Attributes = MemberAttributes.Private; methodOnSignal.Name = signalEventMethodName; methodOnSignal.Parameters.Add(paramdeclSender); methodOnSignal.Parameters.Add(paramdeclSignalEventArgs); methodOnSignal.Statements.Add(new CodeConditionStatement( // * if (this.callbacks != null) new CodeBinaryOperatorExpression(fieldrefCallbacks, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)) // * IEnumerator< <interface>Callback > callbackEnumerator = this.callbacks.GetEnumerator(); , vardeclCallbackEnumerator // * for (bool callbackEnumeratorMoveNext = callbackEnumerator.MoveNext(); callbackEnumeratorMoveNext; callbackEnumeratorMoveNext = callbackEnumerator.MoveNext()) , new CodeIterationStatement(vardeclCallbackEnumeratorMoveNext, varrefCallbackEnumeratorMoveNext, assignCallbackEnumeratorMoveNext , new CodeExpressionStatement(new CodeMethodInvokeExpression(proprefCallbackEnumeratorCurrent, signalEventMethodName, argrefSignalEventArgs)) //// * callbackEnumerator.Current.On<signal>(e); //, new CodeExpressionStatement(new CodeMethodInvokeExpression(arrayindexCallbacks, signalEventMethodName, argrefSignalEventArgs)) ))); typeProxy.Members.Add(methodOnSignal); #endregion #region Write method to register for a signal // * public void RegisterFor<signal>() CodeMethodReferenceExpression methodrefGetCallbackChannel = new CodeMethodReferenceExpression(proprefOperationContextCurrent, "GetCallbackChannel", typerefWCFCallbackInterface); CodeMethodReferenceExpression methodrefOnSignal = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), methodOnSignal.Name); CodeMemberMethod methodRegisterForSignal = new CodeMemberMethod(); methodRegisterForSignal.Attributes = MemberAttributes.Public; methodRegisterForSignal.Name = CodeBuilderCommon.GetSignalRegisterFunction(idlSignal.Name); // * <interface> target = this.GetWCFMethodTarget(); methodRegisterForSignal.Statements.Add(this.DeclareTargetVariable(typerefDbusInterface, typerefDbusMarshal)); // * AddCallback(System.ServiceModel.OperationContext.Current.GetCallbackChannel<I<interface>Callback>()); methodRegisterForSignal.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), methodAddCallback.Name , new CodeMethodInvokeExpression(methodrefGetCallbackChannel)) )); CodePropertyReferenceExpression proprefDbusServiceSignal = new CodePropertyReferenceExpression(fieldrefDbusServices, CodeBuilderCommon.GetSignalEventPropertyName(idlSignal.Name)); CodeAttachEventStatement attacheventSignal = new CodeAttachEventStatement(new CodeEventReferenceExpression(varrefTarget, CodeBuilderCommon.GetSignalEventPropertyName(idlSignal.Name)), methodrefOnSignal); methodRegisterForSignal.Statements.Add(attacheventSignal); typeProxy.Members.Add(methodRegisterForSignal); #endregion } // Ends loop over signals }
override protected void PostHandleSignal(IDLInterface idlIntf, IDLSignal idlSignal, CodeCompileUnit unit, CodeNamespace ns, CodeTypeDeclaration typeInterface) { string nsName, intf; int lastDot = idlIntf.Name.LastIndexOf('.'); intf = idlIntf.Name.Substring(lastDot + 1); nsName = CodeBuilderCommon.GetNamespace(idlIntf.Name, new InterfaceVisitor()); CodeFieldReferenceExpression fieldrefCallback = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), CodeBuilderCommon.callback); CodeFieldReferenceExpression fieldrefTarget = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), CodeBuilderCommon.targetName); CodeNamespace nsClient = this.GetClientNamespace(unit, idlIntf.Name); CodeNamespace nsClientTypes = nsClient; if (this.typedeclCallbackInterface == null) // If no callback interface yet { CodeTypeReference typerefInterface = new CodeTypeReference(typeInterface.Name); // Declare callback interface and hold onto it in field. // * public interface I<interface>Callback // * { string nsWCFName, intfWCF; nsWCFName = CodeBuilderCommon.GetNamespace(idlIntf.Name, this.visitorType); intfWCF = CodeBuilderCommon.GetName(idlIntf.Name, null); string callbackInterfaceName = CodeBuilderCommon.GetSignalCallbackInterfaceName(intfWCF); typedeclCallbackInterface = new CodeTypeDeclaration(callbackInterfaceName); typedeclCallbackInterface.Attributes = MemberAttributes.Public; typedeclCallbackInterface.IsInterface = true; ns.Types.Add(typedeclCallbackInterface); // * class <interface>CallbackClient : I<interface>Callback string wcfCallbackClientName = CodeBuilderCommon.GetSignalCompilableName(intfWCF) + "CallbackClient"; CodeTypeReference typerefCallbackInterface = new CodeTypeReference(typedeclCallbackInterface.Name); CodeAttributeDeclaration attribdeclServiceContract = new CodeAttributeDeclaration(CodeBuilderCommon.typerefServiceContract, new CodeAttributeArgument("CallbackContract", new CodeTypeOfExpression(typerefCallbackInterface)) ); typeInterface.CustomAttributes.Add(attribdeclServiceContract); //string scopedCallbackInterfaceName = CodeBuilderCommon.GetScopedName(nsWCFName, proxyInterfaceName); //typedeclCallbackClient = new CodeTypeDeclaration(CodeBuilderCommon.GetSignalCallbackName(intf)); typedeclCallbackClient = new CodeTypeDeclaration(wcfCallbackClientName); CodeTypeReference typerefWCFCallbackInterface = new CodeTypeReference(typedeclCallbackInterface.Name); typedeclCallbackClient.BaseTypes.Add(typerefWCFCallbackInterface); nsClientTypes.Types.Add(typedeclCallbackClient); // * public class <interface>Proxy : Udbus.WCF.Client.CallbackProxy< <wcf_contracts.interface>, <interface>CallbackClient > this.typedeclProxy = new CodeTypeDeclaration(CodeBuilderCommon.GetSignalProxyName(intfWCF)); CodeTypeReference typerefCallbackProxy = new CodeTypeReference(typeof(Udbus.WCF.Client.CallbackProxy <,>)); CodeTypeReference typerefCallbackClient = new CodeTypeReference(typedeclCallbackClient.Name); typerefCallbackProxy.TypeArguments.Add(typerefInterface); typerefCallbackProxy.TypeArguments.Add(typerefCallbackClient); this.typedeclProxy.BaseTypes.Add(typerefCallbackProxy); AddProxyConstructors(this.typedeclProxy); nsClientTypes.Types.Add(this.typedeclProxy); } // Ends if no callback interface yet // Add signal property to Proxy. CodeMemberProperty propProxySignal = CodeBuilderCommon.CreateSignalEventProperty(idlSignal); propProxySignal.Attributes = MemberAttributes.Public | MemberAttributes.Final; CodePropertyReferenceExpression proprefProxyInterface = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "ProxyInterface"); CodePropertyReferenceExpression proprefProxyCallback = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Callback"); CodePropertyReferenceExpression proprefProxyCallbackEvent = new CodePropertyReferenceExpression(proprefProxyCallback, propProxySignal.Name); propProxySignal.GetStatements.Add(new CodeMethodReturnStatement(proprefProxyCallbackEvent)); propProxySignal.SetStatements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(proprefProxyCallbackEvent, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)) , new CodeExpressionStatement(new CodeMethodInvokeExpression(proprefProxyInterface, CodeBuilderCommon.GetSignalRegisterFunction(idlSignal.Name))) )); propProxySignal.SetStatements.Add(new CodeAssignStatement(proprefProxyCallbackEvent, new CodePropertySetValueReferenceExpression())); this.typedeclProxy.Members.Add(propProxySignal); // Add callback method to callback interface. // * [System.ServiceModel.OperationContract(IsOneWay=true)] // * void On<signal>(<interface_ns>.<signal>Args args); CodeMemberMethod methodOnSignal = new CodeMemberMethod(); methodOnSignal.Name = CodeBuilderCommon.GetSignalCallbackMethodName(idlSignal.Name); string signalArgsTypeName = CodeBuilderCommon.GetSignalEventTypeName(idlSignal.Name); string scopedSignalArgsTypeName = CodeBuilderCommon.GetScopedName(nsName, signalArgsTypeName); CodeParameterDeclarationExpression paramdeclSignalArgs = new CodeParameterDeclarationExpression(scopedSignalArgsTypeName, CodeBuilderCommon.SignalArgsName); methodOnSignal.Parameters.Add(paramdeclSignalArgs); methodOnSignal.CustomAttributes.Add(CodeBuilderCommon.attribOperationContractOneWay); typedeclCallbackInterface.Members.Add(methodOnSignal); // Add registration method to wcf interface. // * [System.ServiceModel.OperationContract] // * void RegisterForStorageSpaceLow(); CodeMemberMethod methodRegister = new CodeMemberMethod(); methodRegister.Name = CodeBuilderCommon.GetSignalRegisterFunction(idlSignal.Name); methodRegister.CustomAttributes.Add(CodeBuilderCommon.attribOperationContract); typeInterface.Members.Add(methodRegister); // Add event to callback client implementation. // * private event System.EventHandler< <signal>Args > <signal>Event; CodeMemberEvent eventSignal = CodeBuilderCommon.CreateSignalEvent(idlSignal); typedeclCallbackClient.Members.Add(eventSignal); // * public virtual System.EventHandler< <signal>Args > <signal> // * { // * get { return this.<signal>Event; } // * set { this.<signal>Event = value; } // * } CodeMemberProperty propSignal = CodeBuilderCommon.CreateSignalEventProperty(idlSignal); propSignal.Attributes = MemberAttributes.Public | MemberAttributes.Final; CodeEventReferenceExpression eventrefSignal = new CodeEventReferenceExpression(new CodeThisReferenceExpression(), eventSignal.Name); propSignal.GetStatements.Add(new CodeMethodReturnStatement(eventrefSignal)); propSignal.SetStatements.Add(new CodeAssignStatement(eventrefSignal, new CodePropertySetValueReferenceExpression())); typedeclCallbackClient.Members.Add(propSignal); // * public void On<signal>(<ns>.<signal>Args args) // * { // * if (this.<signal> != null) // * { // * this.<signal>(this, args); // * } //} CodeMemberMethod methodSignal = new CodeMemberMethod(); methodSignal.Name = CodeBuilderCommon.GetSignalCallbackMethodName(idlSignal.Name); methodSignal.Attributes = MemberAttributes.Public; methodSignal.Parameters.Add(paramdeclSignalArgs); CodePropertyReferenceExpression proprefSignal = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), propSignal.Name); methodSignal.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(eventrefSignal, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)) , new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), eventrefSignal.EventName, new CodeThisReferenceExpression(), new CodeArgumentReferenceExpression(paramdeclSignalArgs.Name))) )); typedeclCallbackClient.Members.Add(methodSignal); }