/// <summary> /// Checks if the contract is valid, and throws if it is not. /// </summary> /// <param name="contract">The contract to check.</param> protected virtual void ValidateContract(ContractDefinition contract) { // Null check if (contract == null) { throw new ArgumentNullException(nameof(contract)); } // Make sure we have a valid name, as the generated class will have this name if (!CSharpNamingUtils.IsValidIdentifier(contract.Name)) { throw new ArgumentException($"Contract name is not a valid C# identifier: {contract.Name}", nameof(contract)); } }
/// <summary> /// Generates the transmitter class. /// </summary> /// <param name="contract">The contract for which to generate the transmitter class.</param> /// <param name="implementationName">The name of the ouput class. This will also be the name of the output file before appending the extension.</param> /// <param name="namespace">The namespace in which to put the generated classes.</param> /// <param name="accessLevel">The access level of the generated classes.</param> public string Run( ContractDefinition contract, string implementationName, string @namespace, CSharpAccessModifier accessLevel = CSharpAccessModifier.Public) { if (contract == null) { throw new ArgumentNullException(nameof(contract)); } if (implementationName == null) { throw new ArgumentNullException(nameof(implementationName)); } if (!CSharpNamingUtils.IsValidIdentifier(implementationName)) { throw new ArgumentException($"Implementation name must be a valid class name: {implementationName}", nameof(implementationName)); } if (@namespace == null) { throw new ArgumentNullException(nameof(@namespace)); } foreach (string namespacePart in @namespace.Split('.')) { if (!CSharpNamingUtils.IsValidIdentifier(namespacePart)) { throw new ArgumentException($"The provided namespace is invalid because the part '{namespacePart}' is not a valid C# identifier: {@namespace}", nameof(@namespace)); } } // Validate the contract this.ValidateContract(contract); // Generate the code CSharpFile file = this.GenerateCode(contract, implementationName, @namespace, accessLevel); string result = file.ToString(); return(result); }
private string GetMethodBody(OperationDefinition operation, bool isAsync, Type returnType) { string parametersVarName = "_parameters"; string operationVarName = "_operation"; string resultVarName = "_result"; StringBuilder sb = new StringBuilder(); // Get the parameters to the operation invocation string parameterValueTypeName = typeof(ParameterValue).GetCSharpName(); sb.AppendLine("// Create the parameters list if needed"); sb.Append($"{parameterValueTypeName}[] {parametersVarName} = "); if (!operation.Parameters.Any()) { sb.AppendLine("null;"); } else { // Create a new array of parameter values sb.AppendLine($"new {parameterValueTypeName}[] {{"); // Add each parameter value foreach (ParameterDefinition parameter in operation.Parameters) { string parameterName = CSharpNamingUtils.SanitizeIdentifier(parameter.Name); sb.AppendLine($"new {parameterValueTypeName}(nameof({parameterName}), {parameter.Name}, \"{parameter.Type.FullName}\"),".Indent()); } // Close the array sb.AppendLine("};"); } sb.AppendLine(); // Create the operation invocation object bool returnsValue = returnType != typeof(void); string operationTypeNameString = typeof(OperationInvocation).GetCSharpName(); sb.AppendLine("// Create an object to represent the operation invocation"); sb.AppendLine($"{operationTypeNameString} {operationVarName} = new {operationTypeNameString}(nameof({operation.Name}), {parametersVarName}, {(returnsValue ? "true" : "false")});"); sb.AppendLine(); // Call the appropriate transmit function, depending on whether or not it is 1) async or 2) needs to return a value sb.AppendLine("// Transmit the operation invocation so a receiver can forward it to an implementation which can execute it"); if (returnsValue) { // Has a return value string returnTypeNameString = returnType.GetCSharpName(); if (isAsync) { sb.AppendLine($"{returnTypeNameString} {resultVarName} = await this.{nameof(Transmitter.RequestTransmitter)}.{nameof(IOperationInvocationTransmitter.TransmitRequestAsync)}<{returnTypeNameString}>({operationVarName});"); } else { sb.AppendLine($"{returnTypeNameString} {resultVarName} = this.{nameof(Transmitter.RequestTransmitter)}.{nameof(IOperationInvocationTransmitter.TransmitRequest)}<{returnTypeNameString}>({operationVarName});"); } sb.AppendLine(); sb.Append($"return {resultVarName};"); } else { // Has no return value if (isAsync) { sb.AppendLine($"await this.{nameof(Transmitter.RequestTransmitter)}.{nameof(IOperationInvocationTransmitter.TransmitMessageAsync)}({operationVarName});"); } else { sb.AppendLine($"this.{nameof(Transmitter.RequestTransmitter)}.{nameof(IOperationInvocationTransmitter.TransmitMessage)}({operationVarName});"); } sb.AppendLine(); sb.Append("return;"); } string result = sb.ToString(); return(result); }