internal static CodeMemberProperty CreateSignalEventProperty(IDLSignal idlSignal) { CodeTypeReference typerefEvent = new CodeTypeReference(typeof(System.EventHandler <>)); typerefEvent.TypeArguments.Add(new CodeTypeReference(CodeBuilderCommon.GetSignalEventTypeName(idlSignal.Name))); CodeMemberProperty propEventSignal = new CodeMemberProperty(); propEventSignal.Name = CodeBuilderCommon.GetSignalEventPropertyName(idlSignal.Name); propEventSignal.Type = typerefEvent; return(propEventSignal); }
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 }