private CodeExpression CreateFunctionParameter(CodeMemberMethod method, UniqueIdentifierService uniqueIdentifierService, FunctionParameter parameter) { // get (adjusted) name of parameter string adjustedParameterName; if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName)) { Debug.Fail("parameter must be registered in identifier service"); } Type parameterType = DetermineParameterType(parameter); // make sure the variable name does not collide with any parameters to the method, or any // existing variables (all registered in the service) string variableName = uniqueIdentifierService.AdjustIdentifier(parameter.Name + "Parameter"); // ObjectParameter variableName; // if (null != parameterName) // { // variableName = new ObjectParameter("parameterName", adjustedParameterName); // } // else // { // variableName = new ObjectParameter("parameterName", typeof(parameterType)); // } method.Statements.Add( new CodeVariableDeclarationStatement(TypeReference.ForType(typeof(ObjectParameter)), variableName)); CodeExpression variableReference = new CodeVariableReferenceExpression(variableName); CodeExpression parameterReference = new CodeVariableReferenceExpression(adjustedParameterName); CodeStatement nullConstructor = new CodeAssignStatement(variableReference, new CodeObjectCreateExpression(TypeReference.ForType(typeof(ObjectParameter)), new CodePrimitiveExpression(parameter.Name), new CodeTypeOfExpression(TypeReference.ForType(parameterType)))); CodeStatement valueConstructor = new CodeAssignStatement(variableReference, new CodeObjectCreateExpression(TypeReference.ForType(typeof(ObjectParameter)), new CodePrimitiveExpression(parameter.Name), parameterReference)); CodeExpression notNullCondition; if (parameterType.IsValueType) { // Value type parameters generate Nullable<ValueType> arguments (see CreateFunctionArgument). // We call Nullable<ValueType>.HasValue to determine whether the argument passed in is null // (since null != nullableTypeInstance does not work in VB) // // parameterReference.HasValue notNullCondition = new CodePropertyReferenceExpression( parameterReference, "HasValue"); } else { // use parameterReference != null notNullCondition = new CodeBinaryOperatorExpression( parameterReference, CodeBinaryOperatorType.IdentityInequality, NullExpression); } method.Statements.Add( new CodeConditionStatement( notNullCondition, new CodeStatement[] { valueConstructor, }, new CodeStatement[] { nullConstructor, } ) ); return variableReference; }
/// <summary> /// Create a method entry point for a function import yielding an entity reader. /// </summary> /// <param name="functionImport">SOM for function import; must not be null and must yield /// an entity reader.</param> /// <returns>Method definition.</returns> private CodeMemberMethod CreateFunctionImportStructuralTypeReaderMethod(EdmFunction functionImport) { // Trying to get: // ///// <summary> ///// Documentation ///// </summary> //public ObjectQueryResult<MyType> MyFunctionImport(Nullable<int> id, string foo) //{ // ObjectParameter idParameter; // if (id.HasValue) // { // idParameter = new ObjectParameter("id", id); // } // else // { // idParameter = new ObjectParameter("id", typeof(int)); // } // ObjectParameter fooParameter; // if (null != foo) // { // fooParameter = new ObjectParameter("foo", foo); // } // else // { // fooParameter = new ObjectParameter("foo", typeof(string)); // } // return base.ExecuteFunction<MyType>("MyFunctionImport", idParameter, fooParameter); //} Debug.Assert(null != functionImport); CodeMemberMethod method = new CodeMemberMethod(); Generator.AttributeEmitter.EmitGeneratedCodeAttribute(method); method.Name = functionImport.Name; method.Attributes = GetFunctionImportAccessibility(functionImport) | MemberAttributes.Final; UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( this.Generator.IsLanguageCaseSensitive, s => Utils.FixParameterName(s)); // determine element return type EdmType returnType = GetReturnTypeFromFunctionImport(functionImport); if (Helper.IsCollectionType(returnType)) { // get the type in the collection returnType = ((CollectionType)returnType).TypeUsage.EdmType; } CodeTypeReference elementType = Generator.GetLeastPossibleQualifiedTypeReference(returnType); method.ReturnType = TypeReference.ObjectResult(elementType); // generate <summary> comments based on CSDL Documentation element CommentEmitter.EmitSummaryComments(functionImport, method.Comments); // build up list of arguments to ExecuteFunction List<CodeExpression> executeArguments = new List<CodeExpression>(); executeArguments.Add(new CodePrimitiveExpression(functionImport.Name)); // first argument is the name of the function foreach (FunctionParameter parameter in functionImport.Parameters) { CreateFunctionArgument(method, uniqueIdentifierService, parameter); } // add fields representing object parameters foreach (FunctionParameter parameter in functionImport.Parameters) { if (parameter.Mode == ParameterMode.In) { CodeExpression variableReference = CreateFunctionParameter(method, uniqueIdentifierService, parameter); executeArguments.Add(variableReference); } else { // the parameter is already being passed in as an argument; just remember it and // pass it in as an argument string adjustedParameterName; if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName)) { Debug.Fail("parameter must be registered in identifier service"); } executeArguments.Add(new CodeVariableReferenceExpression(adjustedParameterName)); } } // Add call to ExecuteFunction // return ExecuteFunction<elementType>("FunctionImportName", { object parameters }); CodeMethodReferenceExpression executeFunctionMethod = new CodeMethodReferenceExpression( new CodeBaseReferenceExpression(), "ExecuteFunction", new CodeTypeReference[] { elementType }); method.Statements.Add( new CodeMethodReturnStatement( new CodeMethodInvokeExpression(executeFunctionMethod, executeArguments.ToArray()) ) ); // invoke the ExecuteFunction method passing in parameters return method; }