Exemple #1
0
        private void GenerateParameterDeclaration(IEnumerable <DomainOperationParameter> parameters, bool generateAttributes)
        {
            DomainOperationParameter[] paramInfos = parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];
                if (generateAttributes)
                {
                    IEnumerable <Attribute> paramAttributes = paramInfo.Attributes.Cast <Attribute>();
                    this.GenerateAttributes(paramAttributes);
                }
                string paramTypeName = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(paramInfo.ParameterType));
                string paramName     = CodeGenUtilities.GetSafeName(paramInfo.Name);

                this.Write(this.ToStringHelper.ToStringWithCulture(paramTypeName));

                this.Write(" ");

                this.Write(this.ToStringHelper.ToStringWithCulture(paramName));


                if (i + 1 < paramInfos.Length)
                {
                    this.Write(", ");
                }
            }
        }
 /// <summary>
 /// Converts input parameters in place.
 /// </summary>
 /// <param name="inputs">Input parameters.</param>
 protected override void ConvertInputs(object[] inputs)
 {
     for (int i = 0; i < this.operation.Parameters.Count; i++)
     {
         DomainOperationParameter parameter = this.operation.Parameters[i];
         inputs[i] = TypeUtils.GetServerValue(parameter.ParameterType, inputs[i]);
     }
 }
Exemple #3
0
        private void GenerateParameterDeclaration(IEnumerable <DomainOperationParameter> parameters, bool generateAttributes)
        {
            DomainOperationParameter[] paramInfos = parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];
                if (generateAttributes)
                {
                    IEnumerable <Attribute> paramAttributes = paramInfo.Attributes.Cast <Attribute>();
                    this.GenerateAttributes(paramAttributes);
                }
                string paramTypeName = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(paramInfo.ParameterType));
                string paramName     = CodeGenUtilities.GetSafeName(paramInfo.Name);


        #line default
        #line hidden

        #line 79 "C:\Code\Repos\openriaservices\OpenRiaServices.DomainServices.Tools.TextTemplate\Framework\CSharpGenerators\Templates\Utility.ttinclude"
                this.Write(this.ToStringHelper.ToStringWithCulture(paramTypeName));


        #line default
        #line hidden

        #line 79 "C:\Code\Repos\openriaservices\OpenRiaServices.DomainServices.Tools.TextTemplate\Framework\CSharpGenerators\Templates\Utility.ttinclude"
                this.Write(" ");


        #line default
        #line hidden

        #line 79 "C:\Code\Repos\openriaservices\OpenRiaServices.DomainServices.Tools.TextTemplate\Framework\CSharpGenerators\Templates\Utility.ttinclude"
                this.Write(this.ToStringHelper.ToStringWithCulture(paramName));


        #line default
        #line hidden

        #line 79 "C:\Code\Repos\openriaservices\OpenRiaServices.DomainServices.Tools.TextTemplate\Framework\CSharpGenerators\Templates\Utility.ttinclude"

                if (i + 1 < paramInfos.Length)
                {
        #line default
        #line hidden

        #line 82 "C:\Code\Repos\openriaservices\OpenRiaServices.DomainServices.Tools.TextTemplate\Framework\CSharpGenerators\Templates\Utility.ttinclude"
                    this.Write(", ");


        #line default
        #line hidden

        #line 82 "C:\Code\Repos\openriaservices\OpenRiaServices.DomainServices.Tools.TextTemplate\Framework\CSharpGenerators\Templates\Utility.ttinclude"
                }
            }
        }
        /// <summary>
        /// Determines whether the specified <see cref="DomainOperationEntry"/> can legally
        /// be generated.  Logs warnings or errors as appropriate.
        /// </summary>
        /// <param name="domainOperationEntry">The operation to generate.</param>
        /// <returns><c>false</c> means an error or warning has been logged and it should not be generated.</returns>
        private bool CanGenerateDomainOperationEntry(DomainOperationEntry domainOperationEntry)
        {
            string methodName = (domainOperationEntry.Operation == DomainOperation.Query) ? domainOperationEntry.Name : domainOperationEntry.Name + QuerySuffix;

            // Check for name conflicts.  Log error and exit if collision.
            if (this._proxyClass.Members.Cast <CodeTypeMember>().Any(c => c.Name == methodName))
            {
                this.ClientProxyGenerator.LogError(
                    string.Format(CultureInfo.CurrentCulture,
                                  Resource.ClientCodeGen_NamingCollision_MemberAlreadyExists,
                                  this._proxyClass.Name,
                                  methodName));

                return(false);
            }

            // Check each parameter type to see if is enum
            DomainOperationParameter[] paramInfos = domainOperationEntry.Parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // If this is an enum type, we need to ensure it is either shared or
                // can be generated.  Failure logs an error.  The test for legality also causes
                // the enum to be generated if required.
                Type enumType = TypeUtility.GetNonNullableType(paramInfo.ParameterType);
                if (enumType.IsEnum)
                {
                    string errorMessage = null;
                    if (!this.ClientProxyGenerator.CanExposeEnumType(enumType, out errorMessage))
                    {
                        this.ClientProxyGenerator.LogError(string.Format(CultureInfo.CurrentCulture,
                                                                         Resource.ClientCodeGen_Domain_Op_Enum_Error,
                                                                         domainOperationEntry.Name,
                                                                         this._proxyClass.Name,
                                                                         enumType.FullName,
                                                                         errorMessage));
                        return(false);
                    }
                    else
                    {
                        // Register use of this enum type, which could cause deferred generation
                        this.ClientProxyGenerator.RegisterUseOfEnumType(enumType);
                    }
                }
            }
            return(true);
        }
Exemple #5
0
        internal bool CanGenerateDomainOperationEntry(DomainOperationEntry domainOperationEntry)
        {
            string methodName = (domainOperationEntry.Operation == DomainOperation.Query) ? domainOperationEntry.Name : domainOperationEntry.Name + QuerySuffix;

            // Check each parameter type to see if is enum
            DomainOperationParameter[] paramInfos = domainOperationEntry.Parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // If this is an enum type, we need to ensure it is either shared or
                // can be generated.  Failure logs an error.  The test for legality also causes
                // the enum to be generated if required.
                Type enumType = TypeUtility.GetNonNullableType(paramInfo.ParameterType);
                if (enumType.IsEnum)
                {
                    string errorMessage = null;
                    if (!this.ClientCodeGenerator.CanExposeEnumType(enumType, out errorMessage))
                    {
                        this.ClientCodeGenerator.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture,
                                                                                           Resource.ClientCodeGen_Domain_Op_Enum_Error,
                                                                                           domainOperationEntry.Name,
                                                                                           this.DomainContextTypeName,
                                                                                           enumType.FullName,
                                                                                           errorMessage));
                        return(false);
                    }
                    else
                    {
                        // Register use of this enum type, which could cause deferred generation
                        this.ClientCodeGenerator.AddEnumTypeToGenerate(enumType);
                    }
                }
            }
            return(true);
        }
Exemple #6
0
        private static OperationDescription CreateOperationDescription(ContractDescription declaringContract, DomainOperationEntry operation)
        {
            OperationDescription operationDesc = ServiceUtility.CreateBasicOperationDescription(declaringContract, operation.Name);

            // Propagate behaviors.
            foreach (IOperationBehavior behavior in operation.Attributes.OfType <IOperationBehavior>())
            {
                operationDesc.Behaviors.Add(behavior);
            }

            // Add standard behaviors.

            if ((operation.Operation == DomainOperation.Query && ((QueryAttribute)operation.OperationAttribute).HasSideEffects) ||
                (operation.Operation == DomainOperation.Invoke && ((InvokeAttribute)operation.OperationAttribute).HasSideEffects))
            {
                // REVIEW: We should actually be able to remove the following line entirely, since
                //         all operations are [WebInvoke] by default.
                ServiceUtility.EnsureBehavior <WebInvokeAttribute>(operationDesc);
            }
            else if (operation.Operation == DomainOperation.Query && !((QueryAttribute)operation.OperationAttribute).HasSideEffects)
            {
                // This is a query with HasSideEffects == false, allow both POST and GET
                var invoke = ServiceUtility.EnsureBehavior <WebInvokeAttribute>(operationDesc);
                invoke.Method = "*";
                // We need to set URI template in order to allow the normal parameters to be extracted from the Uri
                if (operation.Parameters.Count > 0)
                {
                    invoke.UriTemplate = GetDefaultQueryUriTemplate(operation);
                }
            }
            else
            {
                ServiceUtility.EnsureBehavior <WebGetAttribute>(operationDesc);
            }

            string action = ServiceUtility.GetMessageAction(declaringContract, operationDesc.Name, /* action */ null);

            // Define operation input.
            MessageDescription inputMessageDesc = new MessageDescription(action, MessageDirection.Input);

            inputMessageDesc.Body.WrapperName      = operationDesc.Name;
            inputMessageDesc.Body.WrapperNamespace = ServiceUtility.DefaultNamespace;

            for (int i = 0; i < operation.Parameters.Count; i++)
            {
                DomainOperationParameter parameter = operation.Parameters[i];

                MessagePartDescription parameterPartDesc = new MessagePartDescription(parameter.Name, ServiceUtility.DefaultNamespace)
                {
                    Index = i,
                    Type  = SerializationUtility.GetClientType(parameter.ParameterType)
                };
                inputMessageDesc.Body.Parts.Add(parameterPartDesc);
            }
            operationDesc.Messages.Add(inputMessageDesc);

            // Define operation output.
            string responseAction = ServiceUtility.GetResponseMessageAction(declaringContract, operationDesc.Name, /* action */ null);

            MessageDescription outputMessageDesc = new MessageDescription(responseAction, MessageDirection.Output);

            outputMessageDesc.Body.WrapperName      = operationDesc.Name + "Response";
            outputMessageDesc.Body.WrapperNamespace = ServiceUtility.DefaultNamespace;

            if (operation.ReturnType != typeof(void))
            {
                outputMessageDesc.Body.ReturnValue = new MessagePartDescription(operationDesc.Name + "Result", ServiceUtility.DefaultNamespace)
                {
                    Type = SerializationUtility.GetClientType(operation.ReturnType)
                };
            }
            operationDesc.Messages.Add(outputMessageDesc);

            return(operationDesc);
        }
Exemple #7
0
        /// <summary>
        /// Generates a custom method.
        /// </summary>
        /// <param name="domainMethod">The custom method to be generated.</param>
        protected virtual void GenerateCustomMethod(DomainOperationEntry domainMethod)
        {
            this.Write("public void ");

            this.Write(this.ToStringHelper.ToStringWithCulture(domainMethod.Name));

            this.Write("(");


            List <string> invokeParams = new List <string>();

            DomainOperationParameter[] paramInfos = domainMethod.Parameters.ToArray();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];
                string paramTypeName = CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(paramInfo.ParameterType));

                this.Write(this.ToStringHelper.ToStringWithCulture(paramTypeName));

                this.Write(" ");

                this.Write(this.ToStringHelper.ToStringWithCulture(CodeGenUtilities.GetSafeName(paramInfo.Name)));


                if (i + 1 < paramInfos.Length)
                {
                    this.Write(", ");
                }
                if (i > 0)
                {
                    invokeParams.Add(paramInfo.Name);
                }
            }

            this.Write(")\r\n");


            this.GenerateOpeningBrace();

            this.Write(this.ToStringHelper.ToStringWithCulture(paramInfos[0].Name));

            this.Write(".");

            this.Write(this.ToStringHelper.ToStringWithCulture(domainMethod.Name));

            this.Write("(");


            for (int i = 0; i < invokeParams.Count; i++)
            {
                this.Write(this.ToStringHelper.ToStringWithCulture(invokeParams[i]));


                if (i + 1 < invokeParams.Count)
                {
                    this.Write(", ");
                }
            }

            this.Write(");\r\n");


            this.GenerateClosingBrace();
        }
        internal static bool TryValidateMethodCall(DomainOperationEntry operationEntry, ValidationContext validationContext, object[] parameters, List <ValidationResult> validationResults)
        {
            bool breakOnFirstError = validationResults == null;

            ValidationContext methodContext = CreateValidationContext(validationContext.ObjectInstance, validationContext);

            methodContext.MemberName = operationEntry.Name;

            DisplayAttribute display = (DisplayAttribute)operationEntry.Attributes[typeof(DisplayAttribute)];

            if (display != null)
            {
                methodContext.DisplayName = display.GetName();
            }

            string methodPath = string.Empty;

            if (operationEntry.Operation == DomainOperation.Custom)
            {
                methodPath = operationEntry.Name + ".";
            }

            IEnumerable <ValidationAttribute> validationAttributes = operationEntry.Attributes.OfType <ValidationAttribute>();
            bool success = Validator.TryValidateValue(validationContext.ObjectInstance, methodContext, validationResults, validationAttributes);

            if (!breakOnFirstError || success)
            {
                for (int paramIndex = 0; paramIndex < operationEntry.Parameters.Count; paramIndex++)
                {
                    DomainOperationParameter methodParameter = operationEntry.Parameters[paramIndex];
                    object value = (parameters.Length > paramIndex ? parameters[paramIndex] : null);

                    ValidationContext parameterContext = ValidationUtilities.CreateValidationContext(validationContext.ObjectInstance, validationContext);
                    parameterContext.MemberName = methodParameter.Name;

                    string paramName = methodParameter.Name;

                    AttributeCollection parameterAttributes = methodParameter.Attributes;
                    display = (DisplayAttribute)parameterAttributes[typeof(DisplayAttribute)];

                    if (display != null)
                    {
                        paramName = display.GetName();
                    }

                    parameterContext.DisplayName = paramName;

                    string parameterPath = string.Empty;
                    if (!string.IsNullOrEmpty(methodPath) && paramIndex > 0)
                    {
                        parameterPath = methodPath + methodParameter.Name;
                    }

                    IEnumerable <ValidationAttribute> parameterValidationAttributes = parameterAttributes.OfType <ValidationAttribute>();
                    bool parameterSuccess = ValidationUtilities.ValidateValue(value, parameterContext, validationResults, parameterValidationAttributes,
                                                                              ValidationUtilities.NormalizeMemberPath(parameterPath, methodParameter.ParameterType));

                    // Custom methods run deep validation as well as parameter validation.
                    // If parameter validation has already failed, stop further validation.
                    if (parameterSuccess && operationEntry.Operation == DomainOperation.Custom && value != null)
                    {
                        Type parameterType = methodParameter.ParameterType;

                        if (TypeUtility.IsComplexType(parameterType))
                        {
                            parameterSuccess = ValidationUtilities.ValidateObjectRecursive(value, parameterPath, parameterContext, validationResults);
                        }
                        else if (TypeUtility.IsComplexTypeCollection(parameterType))
                        {
                            parameterSuccess = ValidationUtilities.ValidateComplexCollection(value as IEnumerable, parameterPath, parameterContext, validationResults);
                        }
                    }

                    success &= parameterSuccess;

                    if (breakOnFirstError && !success)
                    {
                        break;
                    }
                }
            }

            return(success);
        }
Exemple #9
0
        private void GenerateCustomMethod(DomainOperationEntry customMethod)
        {
            string methodInvokingName = "On" + customMethod.Name + "Invoking";
            string methodInvokedName  = "On" + customMethod.Name + "Invoked";
            List <KeyValuePair <string, string> > customMethodParameters       = new List <KeyValuePair <string, string> >();
            List <DomainOperationParameter>       domainOperationparameterList = new List <DomainOperationParameter>();

            for (int i = 1; i < customMethod.Parameters.Count(); i++)
            {
                DomainOperationParameter paramInfo = customMethod.Parameters[i];
                customMethodParameters.Add(new KeyValuePair <string, string>(CodeGenUtilities.GetTypeName(CodeGenUtilities.TranslateType(paramInfo.ParameterType)), paramInfo.Name));
                domainOperationparameterList.Add(paramInfo);
            }

            var  customMethodAttribute    = customMethod.OperationAttribute as EntityActionAttribute;
            bool allowMultipleInvocations = customMethodAttribute != null && customMethodAttribute.AllowMultipleInvocations;

            this.Write("[OpenRiaServices.DomainServices.Client.EntityAction(\"");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("\", AllowMultipleInvocations = ");

            this.Write(this.ToStringHelper.ToStringWithCulture(allowMultipleInvocations.ToString().ToLower()));

            this.Write(")]\r\npublic void ");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("(");


            this.GenerateParameterDeclaration(domainOperationparameterList, true);

            this.Write(")\r\n");


            this.GenerateOpeningBrace();

            this.Write("this.");

            this.Write(this.ToStringHelper.ToStringWithCulture(methodInvokingName));

            this.Write("(");

            this.GenerateParametersForMethodCall(domainOperationparameterList);
            this.Write(");\r\nbase.InvokeAction(\"");

            this.Write(this.ToStringHelper.ToStringWithCulture(customMethod.Name));

            this.Write("\"");

            if (domainOperationparameterList.Count > 0)
            {
                this.Write(", ");

                this.GenerateParametersForMethodCall(domainOperationparameterList);
            }
            this.Write(");\r\nthis.");

            this.Write(this.ToStringHelper.ToStringWithCulture(methodInvokedName));

            this.Write("();\r\n");


            this.GenerateClosingBrace();

            this.Write("partial void ");

            this.Write(this.ToStringHelper.ToStringWithCulture(methodInvokingName));

            this.Write("(");

            this.GenerateParameterDeclaration(domainOperationparameterList, false);
            this.Write(");\r\npartial void ");

            this.Write(this.ToStringHelper.ToStringWithCulture(methodInvokedName));

            this.Write("();\r\n");
        }
        private void GenerateCustomMethod(string customMethodName, DomainOperationEntry customMethod)
        {
            this.ClientProxyGenerator.LogMessage(string.Format(CultureInfo.CurrentCulture, Resource.EntityCodeGen_Generating_InvokeMethod, customMethodName));

            // ----------------------------------------------------------------
            // Method decl
            // ----------------------------------------------------------------
            CodeMemberMethod method = new CodeMemberMethod();

            method.Name       = customMethodName;
            method.Attributes = MemberAttributes.Public | MemberAttributes.Final;

            // The custom method parameter list is the same as the domain operation entries -- except for the first parameter
            // which is the entity.  We omit that first parameter in code gen
            DomainOperationParameter[] paramInfos = customMethod.Parameters.ToArray();

            // Generate <summary> doc comment for the custom method body
            string comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_Custom_Method_Summary_Comment, customMethodName);

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

            // Generate <param> doc comment for all the parameters
            for (int i = 1; i < paramInfos.Length; ++i)
            {
                comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_Custom_Method_Parameter_Comment, paramInfos[i].Name);
                method.Comments.AddRange(CodeGenUtilities.GenerateParamCodeComment(paramInfos[i].Name, comment, this.ClientProxyGenerator.IsCSharp));
            }

            // Propagate custom validation attributes from the DomainOperationEntry to this custom method
            var methodAttributes = customMethod.Attributes.Cast <Attribute>().ToList();

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

            // Add [CustomMethod("...")] property
            var  customMethodAttribute    = customMethod.OperationAttribute as EntityActionAttribute;
            bool allowMultipleInvocations = customMethodAttribute != null && customMethodAttribute.AllowMultipleInvocations;

            method.CustomAttributes.Add(

                new CodeAttributeDeclaration(
                    CodeGenUtilities.GetTypeReference(TypeConstants.EntityActionAttributeFullName, (string)this._proxyClass.UserData["Namespace"], false),
                    new CodeAttributeArgument(new CodePrimitiveExpression(customMethodName)),
                    new CodeAttributeArgument("AllowMultipleInvocations",
                                              new CodePrimitiveExpression(allowMultipleInvocations))
                    ));

            // ----------------------------------------------------------------
            // generate custom method body:
            //    this.OnMethodNameInvoking(params);
            //    base.Invoke(methodName, params);
            //    this.OnMethodNameInvoked();
            // ----------------------------------------------------------------
            List <CodeExpression> invokeParams = new List <CodeExpression>();

            invokeParams.Add(new CodePrimitiveExpression(customMethodName));

            // Create an expression for each parameter, and also use this loop to
            // propagate the custom attributes for each parameter in the DomainOperationEntry to the custom method.
            for (int i = 1; i < paramInfos.Length; ++i)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // build up the method parameter signature from the DomainOperationEntry.MethodInfo
                CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression(
                    CodeGenUtilities.GetTypeReference(
                        CodeGenUtilities.TranslateType(paramInfo.ParameterType),
                        this.ClientProxyGenerator,
                        this._proxyClass),
                    paramInfo.Name);

                // Propagate parameter level validation attributes from custom operation entry.
                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, method.Name, this._proxyClass.Name, ex.InnerException.Message),
                    paramAttributes,
                    paramDecl.CustomAttributes,
                    method.Comments,
                    commentHeader);

                method.Parameters.Add(paramDecl);

                // build up the invoke call parameters
                invokeParams.Add(new CodeVariableReferenceExpression(paramInfo.Name));
            }

            // generate 'OnCustomMethodInvoked/Invoking'
            string methodInvokingName = customMethodName + "Invoking";
            string methodInvokedName  = customMethodName + "Invoked";

            this._notificationMethodGen.AddMethodFor(methodInvokingName, method.Parameters, null);
            this._notificationMethodGen.AddMethodFor(methodInvokedName, null);

            method.Statements.Add(this._notificationMethodGen.GetMethodInvokeExpressionStatementFor(methodInvokingName));
            method.Statements.Add(
                new CodeExpressionStatement(
                    new CodeMethodInvokeExpression(
                        new CodeBaseReferenceExpression(), "InvokeAction", invokeParams.ToArray())));
            method.Statements.Add(this._notificationMethodGen.GetMethodInvokeExpressionStatementFor(methodInvokedName));

            this._proxyClass.Members.Add(method);

            // ----------------------------------------------------------------
            // generate Is<CustomMethod>Invoked property:
            // [Display(AutoGenerateField=false)]
            // public bool IsMyCustomMethodInvoked { get { base.IsActionInvoked(methodName);}}
            // ----------------------------------------------------------------
            CodeMemberProperty invokedProperty = new CodeMemberProperty();

            invokedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            invokedProperty.HasGet     = true;
            invokedProperty.HasSet     = false;
            invokedProperty.Type       = new CodeTypeReference(typeof(bool));
            invokedProperty.GetStatements.Add(new CodeMethodReturnStatement(
                                                  new CodeMethodInvokeExpression(
                                                      new CodeBaseReferenceExpression(),
                                                      "IsActionInvoked",
                                                      new CodeExpression[] { new CodeArgumentReferenceExpression("\"" + customMethodName + "\"") })));
            invokedProperty.Name = GetIsInvokedPropertyName(customMethodName);

            // Generate <summary> doc comment
            comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_Entity_IsInvoked_Property_Summary_Comment, customMethodName);
            invokedProperty.Comments.AddRange(CodeGenUtilities.GenerateSummaryCodeComment(comment, this.ClientProxyGenerator.IsCSharp));

            CodeAttributeDeclaration displayAttribute = CodeGenUtilities.CreateDisplayAttributeDeclaration(this.ClientProxyGenerator, this._proxyClass);

            invokedProperty.CustomAttributes.Add(displayAttribute);

            this._proxyClass.Members.Add(invokedProperty);
        }
        /// <summary>
        /// Generates a domain method on the domain service.
        /// </summary>
        /// <param name="domainMethod">The domain method to generate code for.</param>
        private void GenerateDomainOperationEntry(DomainOperationEntry domainMethod)
        {
            // ----------------------------------------------------------------
            // Method decl
            // ----------------------------------------------------------------
            CodeMemberMethod method = new CodeMemberMethod();

            method.Name       = domainMethod.Name;
            method.Attributes = MemberAttributes.Public | MemberAttributes.Final;

            // ----------------------------------------------------------------
            // generate domain method body:
            //    entity.<methodName>(params);
            // ----------------------------------------------------------------
            List <CodeExpression> invokeParams = new List <CodeExpression>();

            // The domain method parameter list is the same as the domain operation entries.
            DomainOperationParameter[] paramInfos = domainMethod.Parameters.ToArray();

            // Generate the <summary> and <param> doc comments
            string comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_DomainClient_Custom_Method_Summary_Comment, domainMethod.Name, domainMethod.AssociatedType.Name);

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

            // Generate <param> doc comment for all the parameters
            // The first param is the entity
            comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_DomainContext_Custom_Method_Entity_Parameter_Comment, domainMethod.AssociatedType.Name);
            method.Comments.AddRange(CodeGenUtilities.GenerateParamCodeComment(paramInfos[0].Name, comment, this.ClientProxyGenerator.IsCSharp));

            // All subsequent params
            for (int i = 1; i < paramInfos.Length; ++i)
            {
                comment = string.Format(CultureInfo.CurrentCulture, Resource.CodeGen_DomainContext_Custom_Method_Parameter_Comment, paramInfos[i].Name);
                method.Comments.AddRange(CodeGenUtilities.GenerateParamCodeComment(paramInfos[i].Name, comment, this.ClientProxyGenerator.IsCSharp));
            }

            // Create an expression for each parameter
            for (int i = 0; i < paramInfos.Length; i++)
            {
                DomainOperationParameter paramInfo = paramInfos[i];

                // build up the method parameter signature from the DomainOperationEntry.MethodInfo
                CodeParameterDeclarationExpression paramDecl = new CodeParameterDeclarationExpression(
                    CodeGenUtilities.GetTypeReference(
                        CodeGenUtilities.TranslateType(paramInfo.ParameterType),
                        this.ClientProxyGenerator,
                        this._proxyClass),
                    paramInfo.Name);

                method.Parameters.Add(paramDecl);

                // Skip the entity parameter.
                if (i > 0)
                {
                    // build up the invoke call parameters
                    invokeParams.Add(new CodeVariableReferenceExpression(paramInfo.Name));
                }
            }

            method.Statements.Add(
                new CodeExpressionStatement(
                    new CodeMethodInvokeExpression(
                        new CodeVariableReferenceExpression(paramInfos[0].Name), domainMethod.Name, invokeParams.ToArray())));

            this._proxyClass.Members.Add(method);
        }
Exemple #12
0
        /// <summary>
        /// Create operation corresponding to given DomainService operation.
        /// </summary>
        /// <param name="declaringContract">Contract to which operation will belong.</param>
        /// <param name="operation">DomainService operation.</param>
        /// <returns>Created operation.</returns>
        private static OperationDescription CreateOperationDescription(ContractDescription declaringContract, DomainOperationEntry operation)
        {
            OperationDescription operationDesc = new OperationDescription(operation.Name, declaringContract);

            // Propagate behaviors.
            foreach (IOperationBehavior behavior in operation.Attributes.OfType <IOperationBehavior>())
            {
                operationDesc.Behaviors.Add(behavior);
            }

            // Add standard web behaviors.
            if ((operation.Operation == DomainOperation.Query && ((QueryAttribute)operation.OperationAttribute).HasSideEffects) ||
                (operation.Operation == DomainOperation.Invoke && ((InvokeAttribute)operation.OperationAttribute).HasSideEffects))
            {
                // For operations with side-effects i.e. with WebInvoke attribute, we need to build a default GET like
                // URI template so that, the parameter processing is taken care of by the WebHttpBehavior selector.
                WebInvokeAttribute attrib = ServiceUtils.EnsureBehavior <WebInvokeAttribute>(operationDesc);
                if (attrib.UriTemplate == null)
                {
                    attrib.UriTemplate = ODataEndpointFactory.BuildDefaultUriTemplate(operation);
                }
            }
            else
            {
                ServiceUtils.EnsureBehavior <WebGetAttribute>(operationDesc);
            }

            string action = ServiceUtils.GetRequestMessageAction(declaringContract, operationDesc.Name, null);

            // Define operation input.
            MessageDescription inputMessageDesc = new MessageDescription(action, MessageDirection.Input);

            inputMessageDesc.Body.WrapperName      = operationDesc.Name;
            inputMessageDesc.Body.WrapperNamespace = ServiceUtils.DefaultNamespace;

            for (int i = 0; i < operation.Parameters.Count; i++)
            {
                DomainOperationParameter parameter = operation.Parameters[i];

                MessagePartDescription parameterPartDesc = new MessagePartDescription(parameter.Name, ServiceUtils.DefaultNamespace)
                {
                    Index = i,
                    Type  = TypeUtils.GetClientType(parameter.ParameterType)
                };
                inputMessageDesc.Body.Parts.Add(parameterPartDesc);
            }

            operationDesc.Messages.Add(inputMessageDesc);

            // Define operation output.
            string responseAction = ServiceUtils.GetResponseMessageAction(declaringContract, operationDesc.Name, null);

            MessageDescription outputMessageDesc = new MessageDescription(responseAction, MessageDirection.Output);

            outputMessageDesc.Body.WrapperName      = operationDesc.Name + "Response";
            outputMessageDesc.Body.WrapperNamespace = ServiceUtils.DefaultNamespace;

            if (operation.ReturnType != typeof(void))
            {
                outputMessageDesc.Body.ReturnValue = new MessagePartDescription(operationDesc.Name + "Result", ServiceUtils.DefaultNamespace)
                {
                    Type = TypeUtils.GetClientType(operation.ReturnType)
                };
            }
            operationDesc.Messages.Add(outputMessageDesc);

            return(operationDesc);
        }