internal static string ConvertParametersToCsv(CodeExpressionCollection parameters)
        {
            if (parameters.Count == 0)
            {
                return("None");
            }

            string output = parameters.Cast <CodeExpression>().Aggregate(string.Empty,
                                                                         (current, expression) => current + (ConvertCodeExpression(expression) + "  "));

            return(output.TrimEnd().Replace("  ", ", "));
        }
Beispiel #2
0
        private void GenerateMethod(IDLInterface idlIntf, IDLMethod idlMethod
                                    , Udbus.Parsing.ICodeTypeDeclarationHolder contextDeclarationHolder
                                    , CodeTypeReference typerefDbusInterface
                                    , CodeTypeReference typerefDbusMarshal
                                    , CodeTypeDeclaration typeProxy)
        {
            // Straight-forward interface method.
            CodeMemberMethod         methodInterface   = new CodeMemberMethod();
            CodeExpressionCollection interfaceCallArgs = new CodeExpressionCollection();

            methodInterface.Name       = idlMethod.Name;
            methodInterface.Attributes = MemberAttributes.Public;
            Udbus.Parsing.BuildContext context = new Udbus.Parsing.BuildContext(contextDeclarationHolder);

            #region Methods args
            foreach (IDLMethodArgument idlMethodArg in idlMethod.Arguments)
            {
                CodeCommentStatement commentMethod = new CodeCommentStatement(string.Format("{0} {1} \"{2}\"", idlMethodArg.Direction, idlMethodArg.Name, idlMethodArg.Type));
                methodInterface.Comments.Add(commentMethod);
                // Parse the type string for the argument, creating required structs as we go, and returning a type for the argument.
                Udbus.Parsing.IDLArgumentTypeNameBuilderBase nameBuilder = new IDLMethodArgumentTypeNameBuilder(idlIntf, idlMethod);
                ParamCodeTypeFactory paramtypeHolder = new ParamCodeTypeFactory(CodeTypeFactory.Default,
                                                                                idlMethodArg.Direction == "out" ? FieldDirection.Out : FieldDirection.In);
                Udbus.Parsing.CodeBuilderHelper.BuildCodeParamType(paramtypeHolder, nameBuilder, idlMethodArg.Type, context);
                Udbus.Parsing.ICodeParamType paramtype = paramtypeHolder.paramtype;

                // Arguments.
                CodeParameterDeclarationExpression param           = new CodeParameterDeclarationExpression(paramtype.CodeType, idlMethodArg.Name);
                CodeVariableReferenceExpression    varrefMethodArg = new CodeVariableReferenceExpression(idlMethodArg.Name);

                if (idlMethodArg.Direction == "out")
                {
                    // Add to interface parameters.
                    interfaceCallArgs.Add(new CodeDirectionExpression(FieldDirection.Out, varrefMethodArg));
                    // Add parameter to interface method.
                    param.Direction = FieldDirection.Out;
                }
                else
                {
                    interfaceCallArgs.Add(varrefMethodArg);
                }
                methodInterface.Parameters.Add(param);
            } // Ends loop over method arguments
            #endregion

            methodInterface.Statements.Add(this.DeclareTargetVariable(typerefDbusInterface, typerefDbusMarshal));
            methodInterface.Statements.Add(new CodeMethodInvokeExpression(varrefTarget, idlMethod.Name, interfaceCallArgs.Cast <CodeExpression>().ToArray()));

            //methodInterface.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(thisProxyFieldRef, idlMethod.Name)
            //    , interfaceCallArgs.Cast<CodeExpression>().ToArray()
            //));

            // Finish up.
            typeProxy.Members.Add(methodInterface);
        }
Beispiel #3
0
        public override void GenerateMethods(IDLInterface idlIntf)
        {
            if (idlIntf.Methods != null) // If got methods
            {
                bAddNamespace = idlIntf.Methods.Count > 0;

                foreach (IDLMethod idlMethod in idlIntf.Methods)
                {
                    // Structs for capturing input/output from method.
                    Udbus.Parsing.CodeTypeDeferredStructHolder paramsHolder = new Udbus.Parsing.CodeTypeDeferredStructHolder(idlMethod.Name + "AsyncParams");
                    Udbus.Parsing.CodeTypeDeferredStructHolder resultHolder = new Udbus.Parsing.CodeTypeDeferredStructHolder(idlMethod.Name + "AsyncResult");
                    CodeConstructor constructorResults = new CodeConstructor();
                    CodeConstructor constructorParams  = new CodeConstructor();
                    constructorResults.Attributes = constructorParams.Attributes = MemberAttributes.Public;

                    // Create Call method.
                    CodeMemberMethod methodCall = new CodeMemberMethod();
                    methodCall.Name = "Call" + idlMethod.Name;
                    // Actual call to proxy arguments will be added to as we parse IDL arguments.
                    CodeExpressionCollection        callParameters    = new CodeExpressionCollection();
                    CodeExpressionCollection        callResultArgs    = new CodeExpressionCollection();
                    CodeExpressionCollection        interfaceCallArgs = new CodeExpressionCollection();
                    CodeArgumentReferenceExpression argrefCallData    = new CodeArgumentReferenceExpression(dataName);

                    // Event Args
                    string eventName = idlMethod.Name + "EventArgs";
                    CodeTypeDeclaration typeEvent = new CodeTypeDeclaration(eventName);
                    typeEvent.IsClass        = true;
                    typeEvent.TypeAttributes = TypeAttributes.Public;
                    typeEvent.BaseTypes.Add(new CodeTypeReference(typeof(AsyncCompletedEventArgs)));
                    CodeConstructor constructorEventArgs = new CodeConstructor();
                    eventsDeclarationHolder.Add(typeEvent);
                    CodeExpressionCollection makeEventArgs = new CodeExpressionCollection();

                    // Event Raiser...
                    string            raiserName  = "raiser" + idlMethod.Name;
                    CodeTypeReference raiserRef   = new CodeTypeReference("AsyncOperationEventRaiser", new CodeTypeReference(eventName));
                    CodeMemberField   fieldRaiser = new CodeMemberField(raiserRef, raiserName);
                    fieldRaiser.InitExpression = new CodeObjectCreateExpression(raiserRef);
                    fieldRaiser.Attributes     = MemberAttributes.Private;
                    typeProxy.Members.Add(fieldRaiser);

                    // Event raiser EventCompleted Property - unfortunately CodeMemberEvent is useless here since can't add custom add/remove.
                    // So anything other than CSharp is now a bust. Brilliant.
                    CodeSnippetTypeMember eventRaiser = new CodeSnippetTypeMember();
                    eventRaiser.Text = string.Format(@"        public event System.EventHandler<{0}> {1}Completed
        {{
            add {{ this.{2}.CompletedEvent += value; }}
            remove {{ this.{2}.CompletedEvent -= value; }}
        }}
", eventName, idlMethod.Name, raiserName
                                                     ); // Adding text here.

                    //CodeMemberEvent eventRaiser = new CodeMemberEvent();
                    //eventRaiser.Attributes = MemberAttributes.Public;
                    //CodeParamDeclaredType declaredType = new CodeParamDeclaredType(typeEvent);
                    //eventRaiser.Type = new CodeTypeReference(CodeBuilderCommon.EventHandlerType.Name, declaredType.CodeType);
                    //eventRaiser.Name = idlMethod.Name + "Completed";

                    typeProxy.Members.Add(eventRaiser);

                    // Async method.
                    CodeMemberMethod methodAsync = new CodeMemberMethod();
                    methodAsync.Name       = idlMethod.Name + "Async";
                    methodAsync.Attributes = MemberAttributes.Public;

                    // Straight-forward interface method.
                    CodeMemberMethod methodInterface = new CodeMemberMethod();
                    methodInterface.Name       = idlMethod.Name;
                    methodInterface.Attributes = MemberAttributes.Public;

                    //        CodeComment commentMethod = new CodeComment(idlMethod.Name);
                    //        method.Comments.Add(new CodeCommentStatement(idlMethod.Name));
                    CodeExpressionCollection   asyncArgs = new CodeExpressionCollection();
                    Udbus.Parsing.BuildContext context   = new Udbus.Parsing.BuildContext(contextDeclarationHolder);

                    foreach (IDLMethodArgument idlMethodArg in idlMethod.Arguments)
                    {
                        CodeCommentStatement commentMethod = new CodeCommentStatement(string.Format("{0} {1} \"{2}\"", idlMethodArg.Direction, idlMethodArg.Name, idlMethodArg.Type));
                        methodAsync.Comments.Add(commentMethod);
                        methodInterface.Comments.Add(commentMethod);
                        // Parse the type string for the argument, creating required structs as we go, and returning a type for the argument.
                        Udbus.Parsing.IDLArgumentTypeNameBuilderBase nameBuilder = new IDLMethodArgumentTypeNameBuilder(idlIntf, idlMethod);
                        ParamCodeTypeFactory paramtypeHolder = new ParamCodeTypeFactory(CodeTypeFactory.Default,
                                                                                        idlMethodArg.Direction == "out" ? FieldDirection.Out : FieldDirection.In);
                        Udbus.Parsing.CodeBuilderHelper.BuildCodeParamType(paramtypeHolder, nameBuilder, idlMethodArg.Type, context);
                        Udbus.Parsing.ICodeParamType paramtype = paramtypeHolder.paramtype;

                        // Arguments.
                        CodeParameterDeclarationExpression param           = new CodeParameterDeclarationExpression(paramtype.CodeType, idlMethodArg.Name);
                        CodeVariableReferenceExpression    varrefMethodArg = new CodeVariableReferenceExpression(idlMethodArg.Name);

                        if (idlMethodArg.Direction == "out") // If out argument
                        {
                            // Add to interface parameters.
                            interfaceCallArgs.Add(new CodeDirectionExpression(FieldDirection.Out, varrefMethodArg));

                            // Put into result holding struct...
                            param.Direction = FieldDirection.Out;
                            methodInterface.Parameters.Add(param);

                            CodeTypeReference argType        = CodeBuilderCommon.GetReadOnlyCodeReference(paramtypeHolder.paramtype.CodeType);
                            CodeMemberField   fieldResultArg = new CodeMemberField(argType, idlMethodArg.Name);
                            fieldResultArg.Attributes = MemberAttributes.Public;
                            resultHolder.CodeType.Members.Add(fieldResultArg);

                            constructorResults.Parameters.Add(new CodeParameterDeclarationExpression(paramtype.CodeType, idlMethodArg.Name));
                            CodeFieldReferenceExpression thisArg = new CodeFieldReferenceExpression(
                                new CodeThisReferenceExpression(), idlMethodArg.Name
                                );
                            constructorResults.Statements.Add(new CodeAssignStatement(thisArg,
                                                                                      new CodeArgumentReferenceExpression(idlMethodArg.Name)));

                            // Add placeholder variables to call method.
                            methodCall.Statements.Add(new CodeVariableDeclarationStatement(paramtype.CodeType, idlMethodArg.Name));

                            // Add appropriate parameter in actual call to interface.
                            callParameters.Add(new CodeDirectionExpression(FieldDirection.Out, varrefMethodArg));

                            // Add appropriate parameter in call to result constructor.
                            callResultArgs.Add(new CodeArgumentReferenceExpression(idlMethodArg.Name));

                            // Put into event args class...
                            string          fieldEventArgName = idlMethodArg.Name + "_";
                            CodeMemberField fieldEventArg     = new CodeMemberField(paramtype.CodeType, fieldEventArgName);
                            fieldEventArg.Attributes = MemberAttributes.Private;
                            typeEvent.Members.Add(fieldEventArg);

                            // Add argument property to EventArgs.
                            CodeMemberProperty propEventArg = new CodeMemberProperty();
                            propEventArg.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                            propEventArg.Name       = idlMethodArg.Name;
                            propEventArg.HasGet     = true;
                            propEventArg.Type       = paramtype.CodeType;
                            propEventArg.GetStatements.Add(new CodeMethodInvokeExpression(null, "RaiseExceptionIfNecessary"));
                            propEventArg.GetStatements.Add(new CodeMethodReturnStatement(new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), fieldEventArgName)));
                            typeEvent.Members.Add(propEventArg);

                            // Add constructor parameter and statement to EventArgs.
                            constructorEventArgs.Parameters.Add(new CodeParameterDeclarationExpression(paramtype.CodeType, idlMethodArg.Name));
                            constructorEventArgs.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldEventArgName),
                                                                                        new CodeArgumentReferenceExpression(idlMethodArg.Name)
                                                                                        ));

                            // Add as parameter in call to EventArgs constructor.
                            makeEventArgs.Add(new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression(resultName), idlMethodArg.Name));
                        }    // Ends if out argument
                        else // Else in argument
                        {
                            // Add to interface parameters.
                            interfaceCallArgs.Add(varrefMethodArg);
                            // Put into parameter holding struct.
                            CodeMemberField fieldArg = new CodeMemberField(CodeBuilderCommon.GetReadOnlyCodeReference(paramtype.CodeType), idlMethodArg.Name);
                            fieldArg.Attributes = MemberAttributes.Public;
                            paramsHolder.CodeType.Members.Add(fieldArg);

                            constructorParams.Parameters.Add(new CodeParameterDeclarationExpression(paramtype.CodeType, idlMethodArg.Name));
                            CodeFieldReferenceExpression thisArg = new CodeFieldReferenceExpression(
                                new CodeThisReferenceExpression(), idlMethodArg.Name
                                );
                            constructorParams.Statements.Add(new CodeAssignStatement(thisArg,
                                                                                     new CodeArgumentReferenceExpression(idlMethodArg.Name)));

                            // Add appropriate parameter in actual call to interface.
                            callParameters.Add(new CodeFieldReferenceExpression(argrefCallData, idlMethodArg.Name));

                            // Add appropriate parameter to async method parameters constructor call.
                            asyncArgs.Add(new CodeArgumentReferenceExpression(idlMethodArg.Name));

                            // Add parameter to async method.
                            methodAsync.Parameters.Add(param);
                            // Add parameter to interface method.
                            methodInterface.Parameters.Add(param);
                        } // Ends else in argument
                    }     // Ends loop over method arguments

                    methodAsync.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "userState"));

                    // Add method body, then sort out arguments code...
                    CodeFieldReferenceExpression thisRaiser = new CodeFieldReferenceExpression(
                        new CodeThisReferenceExpression(), raiserName
                        );
                    CodeTypeReference typerefResult = null;
                    if (idlMethod.Return != null) // If method has return type
                    {
                        // Add result to Result type.
                        // TODO replace typeof(string) with actual return type.
                        typerefResult = new CodeTypeReference("???");
                    }

                    CodeTypeReference typerefResults      = null;
                    CodeTypeReference typerefParams       = null;
                    CodeExpression    exprAsyncParamValue = null;
                    string            asyncMethodName     = "AsyncFuncImpl"; // Default is assuming that function returns something.

                    if (paramsHolder.QuType())                               // If got params type
                    {
                        typerefParams = new CodeTypeReference(paramsHolder.CodeType.Name);

                        // Add proxy field to params struct.
                        CodeMemberField memberParamsProxy = new CodeMemberField(new CodeTypeReference("readonly " + genInterfaceName), proxyName);
                        memberParamsProxy.Attributes = MemberAttributes.Public;
                        paramsHolder.CodeType.Members.Insert(0, memberParamsProxy); // TODO: Going to need a using or a fully qualified name.

                        // Add initialisation to constructor
                        constructorParams.Parameters.Insert(0, paramProxy);
                        // Constructor will take proxy as first argument.
                        constructorParams.Statements.Insert(0, assignProxy);


                        paramsHolder.CodeType.TypeAttributes = TypeAttributes.NestedPrivate;
                        paramsHolder.CodeType.IsStruct       = true;
                        constructorParams.Attributes         = MemberAttributes.Public;
                        paramsHolder.CodeType.Members.Add(constructorParams);
                        typeProxy.Members.Add(paramsHolder.CodeType);

                        asyncArgs.Insert(0, thisProxyFieldRef);
                        exprAsyncParamValue = new CodeObjectCreateExpression(typerefParams, asyncArgs.Cast <CodeExpression>().ToArray());
                    } // Ends if got params type

                    if (resultHolder.QuType()) // If got results type
                    {
                        typerefResults = new CodeTypeReference(resultHolder.CodeType.Name);

                        methodCall.ReturnType = typerefResults;

                        // Setup call method parameters.
                        if (idlMethod.Return != null)
                        {
                            // Add result field to EventArgs.
                            CodeMemberField fieldResult = new CodeMemberField(typerefResult, resultName);
                            fieldResult.Attributes = MemberAttributes.Private;
                            typeEvent.Members.Insert(0, fieldResult);

                            // Add result property to EventArgs.
                            CodeMemberProperty propResult = new CodeMemberProperty();
                            propResult.Attributes = MemberAttributes.Public;
                            propResult.Name       = resultName;
                            propResult.HasGet     = true;
                            propResult.Type       = typerefResult;
                            propResult.GetStatements.Add(new CodeMethodInvokeExpression(null, "RaiseExceptionIfNecessary"));
                            propResult.GetStatements.Add(new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), resultName));
                            typeEvent.Members.Add(propResult);

                            // Add suitable parameter as first EventArgs constructor argument.
                            constructorEventArgs.Parameters.Insert(0, new CodeParameterDeclarationExpression(typerefResult, resultName));
                            // Add statement to initialise result member.
                            CodeFieldReferenceExpression thisArg = new CodeFieldReferenceExpression(
                                new CodeThisReferenceExpression(), resultName
                                );

                            // Include result in parameters to EventArgs in MakeEventArgs statements.
                            makeEventArgs.Insert(0, new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), resultName));

                            // Add result to Result type.
                            CodeTypeReference typerefReadOnlyResult = CodeBuilderCommon.GetReadOnlyCodeReference(typerefResult);
                            CodeMemberField   fieldReadOnlyResult   = new CodeMemberField(typerefReadOnlyResult, resultName);
                            fieldResult.Attributes = MemberAttributes.Public;
                            resultHolder.CodeType.Members.Insert(0, fieldReadOnlyResult);

                            // Add suitable parameter as first constructor argument.
                            constructorResults.Parameters.Insert(0, new CodeParameterDeclarationExpression(typerefResult, resultName));
                            // Add statement to initialise result member.
                            constructorResults.Statements.Insert(0, new CodeAssignStatement(thisArg,
                                                                                            new CodeArgumentReferenceExpression(resultName)));
                        } // End if there is a return statement

                        resultHolder.CodeType.TypeAttributes = TypeAttributes.NestedPrivate;
                        resultHolder.CodeType.IsStruct       = true;

                        resultHolder.CodeType.Members.Add(constructorResults);
                        typeProxy.Members.Add(resultHolder.CodeType);
                    }    // Ends if got results type
                    else // Else no results type
                    {
                        // Absolutely no results (including out parameters) means it's an Action.
                        asyncMethodName = "AsyncActionImpl";
                    } // Ends else no results type

                    // Time to bite the bullet.
                    CodeTypeReference typerefEvent        = new CodeTypeReference(typeEvent.Name);
                    CodeMemberMethod  methodMakeEventArgs = new CodeMemberMethod();
                    methodMakeEventArgs.Name = "Make" + idlMethod.Name + "AsyncEventArgs";

                    // Add missing parameters to EventArgs...
                    constructorEventArgs.Parameters.Add(CodeBuilderCommon.paramdeclException);
                    constructorEventArgs.Parameters.Add(CodeBuilderCommon.paramdeclCancelled);
                    constructorEventArgs.Parameters.Add(CodeBuilderCommon.paramdeclUserState);
                    // Pass through to base class.
                    constructorEventArgs.BaseConstructorArgs.Add(CodeBuilderCommon.argrefException);
                    constructorEventArgs.BaseConstructorArgs.Add(CodeBuilderCommon.argrefCancelled);
                    constructorEventArgs.BaseConstructorArgs.Add(CodeBuilderCommon.argrefUserState);

                    // Add MakeEventArgs method...
                    // Create MakeEventArgs method.
                    methodMakeEventArgs.Attributes = MemberAttributes.Private | MemberAttributes.Static;
                    if (typerefParams != null) // If got params type
                    {
                        methodMakeEventArgs.Parameters.Add(new CodeParameterDeclarationExpression(typerefParams, dataName));
                    }
                    else // Else no params type
                    {
                        // The interface will be passed as the first parameter.
                        methodMakeEventArgs.Parameters.Add(paramProxy);
                    } // Ends else no params type

                    if (typerefResults != null) // If got results type
                    {
                        methodMakeEventArgs.Parameters.Add(new CodeParameterDeclarationExpression(typerefResults, resultName));
                    }
                    methodMakeEventArgs.Parameters.Add(CodeBuilderCommon.paramdeclException);
                    methodMakeEventArgs.Parameters.Add(CodeBuilderCommon.paramdeclCancelled);
                    methodMakeEventArgs.Parameters.Add(CodeBuilderCommon.paramdeclUserState);
                    makeEventArgs.Add(CodeBuilderCommon.argrefException);
                    makeEventArgs.Add(CodeBuilderCommon.argrefCancelled);
                    makeEventArgs.Add(CodeBuilderCommon.argrefUserState);
                    methodMakeEventArgs.Statements.Add(new CodeMethodReturnStatement(
                                                           new CodeObjectCreateExpression(
                                                               typerefEvent, makeEventArgs.Cast <CodeExpression>().ToArray()
                                                               )
                                                           ));
                    methodMakeEventArgs.ReturnType = typerefEvent;
                    typeProxy.Members.Add(methodMakeEventArgs);

                    // Setup call method parameters.
                    methodCall.Attributes = MemberAttributes.Private | MemberAttributes.Static;
                    CodeExpression exprProxyRef;
                    //methodCall.ReturnType = new CodeTypeReference(resultHolder.CodeType.Name);
                    if (typerefParams != null) // If passing parameters
                    {
                        methodCall.Parameters.Add(new CodeParameterDeclarationExpression(typerefParams, dataName));
                        exprProxyRef = new CodeFieldReferenceExpression(argrefCallData, proxyName);
                    }    // Ends if passing parameters
                    else // Else just passing proxy
                    {
                        methodCall.Parameters.Add(new CodeParameterDeclarationExpression(genInterfaceName, proxyName));
                        exprProxyRef = new CodeArgumentReferenceExpression(proxyName);
                    } // Ends else just passing proxy

                    // Add call method body...
                    // Invocation to proxy.
                    CodeMethodReferenceExpression methodProxy = new CodeMethodReferenceExpression(exprProxyRef, idlMethod.Name);
                    CodeMethodInvokeExpression    invokeProxy = new CodeMethodInvokeExpression(methodProxy, callParameters.Cast <CodeExpression>().ToArray());
                    if (idlMethod.Return != null) // If got return type
                    {
                        // TODO - return values.
                        // Add invocation of actual interface method and store result.
                        CodeVariableDeclarationStatement exprResult = new CodeVariableDeclarationStatement(typerefResult, resultName, invokeProxy);
                        methodCall.Statements.Add(exprResult);

                        // Initialise result parameter in Result struct.
                        callResultArgs.Insert(0, new CodeArgumentReferenceExpression(resultName));
                    }    // Ends if got return type
                    else // Else no return type
                    {
                        // Add invocation of actual interface method and ignore result.
                        methodCall.Statements.Add(invokeProxy);
                    } // Ends else no return type

                    if (typerefResults != null) // If got result type
                    {
                        // Create Call return statement.
                        CodeMethodReturnStatement retCall = new CodeMethodReturnStatement(
                            new CodeObjectCreateExpression(typerefResults, callResultArgs.Cast <CodeExpression>().ToArray())
                            );
                        methodCall.Statements.Add(retCall);
                    } // Ends if got result type

                    // Add call method to type.
                    typeProxy.Members.Add(methodCall);

                    // Add async method implementation...
                    if (exprAsyncParamValue == null) // If no params
                    {
                        // Just pass the proxy.
                        exprAsyncParamValue = thisProxyFieldRef;
                    } // Ends if no params

                    methodAsync.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(thisRaiser, asyncMethodName)
                                                                              , new CodeArgumentReferenceExpression("userState")
                                                                              , exprAsyncParamValue
                                                                              , new CodeMethodReferenceExpression(null, methodCall.Name)
                                                                              , new CodeMethodReferenceExpression(null, methodMakeEventArgs.Name)
                                                                              ));

                    methodInterface.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(thisProxyFieldRef, idlMethod.Name)
                                                                                  , interfaceCallArgs.Cast <CodeExpression>().ToArray()
                                                                                  ));
                    // Finish up.
                    typeEvent.Members.Add(constructorEventArgs);
                    constructorEventArgs.Attributes = MemberAttributes.Public;
                    ns.Types.Add(typeEvent);
                    typeProxy.Members.Add(methodAsync);
                    typeProxy.Members.Add(methodInterface);
                } // Ends loop over methods
            }     // Ends if got methods
        }
        private void GenerateEntityQueryMethod(DomainOperationEntry domainOperationEntry)
        {
            string queryMethodName = domainOperationEntry.Name + QuerySuffix;

            Type entityType = TypeUtility.GetElementType(domainOperationEntry.ReturnType);

            CodeMemberMethod queryMethod = new CodeMemberMethod();

            queryMethod.Name       = queryMethodName;
            queryMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; // Final needed, else becomes virtual

            queryMethod.ReturnType = CodeGenUtilities.GetTypeReference(TypeConstants.EntityQueryTypeFullName, this._domainServiceDescription.DomainServiceType.Namespace, false);
            queryMethod.ReturnType.TypeArguments.Add(CodeGenUtilities.GetTypeReference(entityType.FullName, this._domainServiceDescription.DomainServiceType.Namespace, true));

            DomainOperationParameter[] domainOperationEntryParameters = domainOperationEntry.Parameters.ToArray();

            // Generate <summary> doc comment
            string comment = string.Format(CultureInfo.CurrentCulture, Resource.EntityCodeGen_ConstructorComments_Summary_DomainContext, entityType.Name, domainOperationEntry.Name);

            queryMethod.Comments.AddRange(CodeGenUtilities.GenerateSummaryCodeComment(comment, this.ClientProxyGenerator.IsCSharp));

            // Generate <param> doc comments
            foreach (DomainOperationParameter paramInfo in domainOperationEntryParameters)
            {
                comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Query_Method_Parameter_Comment, paramInfo.Name);
                queryMethod.Comments.AddRange(CodeGenUtilities.GenerateParamCodeComment(paramInfo.Name, comment, this.ClientProxyGenerator.IsCSharp));
            }

            // Generate <returns> doc comments
            comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Query_Method_Returns_Comment, domainOperationEntry.AssociatedType.Name);
            queryMethod.Comments.AddRange(CodeGenUtilities.GenerateReturnsCodeComment(comment, this.ClientProxyGenerator.IsCSharp));

            // Propagate custom validation attributes
            IEnumerable <Attribute> methodAttributes = domainOperationEntry.Attributes.Cast <Attribute>();

            CustomAttributeGenerator.GenerateCustomAttributes(
                this.ClientProxyGenerator,
                this._proxyClass,
                ex => string.Format(CultureInfo.CurrentCulture, Resource.ClientCodeGen_Attribute_ThrewException_CodeMethod, ex.Message, queryMethod.Name, this._proxyClass.Name, ex.InnerException.Message),
                methodAttributes,
                queryMethod.CustomAttributes,
                queryMethod.Comments);

            // add any domain operation entry parameters first

            CodeVariableReferenceExpression paramsRef = new CodeVariableReferenceExpression("parameters");

            if (domainOperationEntryParameters.Length > 0)
            {
                // need to generate the user parameters dictionary
                CodeTypeReference dictionaryTypeReference = CodeGenUtilities.GetTypeReference(
                    typeof(Dictionary <string, object>),
                    this.ClientProxyGenerator,
                    this._proxyClass);

                CodeVariableDeclarationStatement paramsDef = new CodeVariableDeclarationStatement(
                    dictionaryTypeReference,
                    "parameters",
                    new CodeObjectCreateExpression(dictionaryTypeReference, new CodeExpression[0]));
                queryMethod.Statements.Add(paramsDef);
            }
            foreach (DomainOperationParameter paramInfo in domainOperationEntryParameters)
            {
                CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression(
                    CodeGenUtilities.GetTypeReference(
                        CodeGenUtilities.TranslateType(paramInfo.ParameterType),
                        this.ClientProxyGenerator,
                        this._proxyClass),
                    paramInfo.Name);

                // Propagate parameter level validation attributes
                IEnumerable <Attribute> paramAttributes = paramInfo.Attributes.Cast <Attribute>();

                string commentHeader =
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resource.ClientCodeGen_Attribute_Parameter_FailedToGenerate,
                        paramInfo.Name);

                CustomAttributeGenerator.GenerateCustomAttributes(
                    this.ClientProxyGenerator,
                    this._proxyClass,
                    ex => string.Format(CultureInfo.CurrentCulture, Resource.ClientCodeGen_Attribute_ThrewException_CodeMethodParameter, ex.Message, paramDecl.Name, queryMethod.Name, this._proxyClass.Name, ex.InnerException.Message),
                    paramAttributes,
                    paramDecl.CustomAttributes,
                    queryMethod.Comments,
                    commentHeader);

                // add the parameter to the query method
                queryMethod.Parameters.Add(paramDecl);

                // add the parameter and value to the params dictionary
                queryMethod.Statements.Add(new CodeMethodInvokeExpression(
                                               new CodeMethodReferenceExpression(paramsRef, "Add"),
                                               new CodePrimitiveExpression(paramInfo.Name),
                                               new CodeVariableReferenceExpression(paramInfo.Name)));
            }

            // add argument for queryName
            CodeExpressionCollection arguments = new CodeExpressionCollection();

            arguments.Add(new CodePrimitiveExpression(domainOperationEntry.Name));

            // add argument for parameters
            if (domainOperationEntryParameters.Length > 0)
            {
                arguments.Add(paramsRef);
            }
            else
            {
                arguments.Add(new CodePrimitiveExpression(null));
            }

            // add argument for hasSideEffects
            QueryAttribute queryAttribute = (QueryAttribute)domainOperationEntry.OperationAttribute;

            arguments.Add(new CodePrimitiveExpression(queryAttribute.HasSideEffects));

            // add argument for isComposable
            arguments.Add(new CodePrimitiveExpression(queryAttribute.IsComposable));

            // this.ValidateMethod("methodName", parameters);
            CodeExpression paramsExpr = new CodePrimitiveExpression(null);

            if (domainOperationEntryParameters.Length > 0)
            {
                paramsExpr = paramsRef;
            }
            CodeExpressionStatement validateMethodCall = new CodeExpressionStatement(
                new CodeMethodInvokeExpression(
                    new CodeThisReferenceExpression(),
                    "ValidateMethod",
                    new CodeExpression[]
            {
                new CodePrimitiveExpression(queryMethodName),
                paramsExpr
            }));

            queryMethod.Statements.Add(validateMethodCall);

            // ----------------------------------------------------------------
            // method call: base.CreateQuery(arguments...)
            // ----------------------------------------------------------------
            CodeTypeReference             entityTypeRef     = CodeGenUtilities.GetTypeReference(entityType.FullName, this._domainServiceDescription.DomainServiceType.Namespace, true);
            CodeMethodReferenceExpression createQueryMethod = new CodeMethodReferenceExpression(new CodeBaseReferenceExpression(), "CreateQuery", entityTypeRef);
            CodeMethodReturnStatement     createQueryCall   = new CodeMethodReturnStatement(new CodeMethodInvokeExpression(createQueryMethod, arguments.Cast <CodeExpression>().ToArray()));

            queryMethod.Statements.Add(createQueryCall);

            this._proxyClass.Members.Add(queryMethod);
        }