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]); } }
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); }
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); }
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); }
/// <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); }
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); }
/// <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); }