Ejemplo n.º 1
0
        private static void WriteConstructor(CodeWriter writer, ObjectType schema)
        {
            foreach (var constructor in schema.Constructors)
            {
                writer.WriteXmlDocumentationSummary($"Initializes a new instance of {schema.Declaration.Name}");
                foreach (var parameter in constructor.Parameters)
                {
                    writer.WriteXmlDocumentationParameter(parameter.Name, parameter.Description);
                }

                writer.Append($"{constructor.Declaration.Accessibility} {schema.Declaration.Name}(");
                foreach (var parameter in constructor.Parameters)
                {
                    writer.WriteParameter(parameter);
                }
                writer.RemoveTrailingComma();
                writer.Append($")");

                if (constructor.BaseConstructor?.Parameters.Length > 0)
                {
                    writer.Append($": base(");
                    foreach (var baseConstructorParameter in constructor.BaseConstructor.Parameters)
                    {
                        writer.Append($"{baseConstructorParameter.Name:I}, ");
                    }
                    writer.RemoveTrailingComma();
                    writer.Append($")");
                }

                writer.Line();

                using (writer.Scope())
                {
                    writer.WriteParameterNullChecks(constructor.Parameters);

                    foreach (var initializer in constructor.Initializers)
                    {
                        writer.Append($"{initializer.Property.Declaration.Name} = ")
                        .WriteReferenceOrConstant(initializer.Value)
                        .WriteConversion(initializer.Value.Type, initializer.Property.Declaration.Type);

                        if (initializer.DefaultValue != null &&
                            !initializer.Value.Type.IsValueType)
                        {
                            writer.Append($"?? ").WriteReferenceOrConstant(initializer.DefaultValue.Value);
                        }

                        writer.Line($";");
                    }
                }

                writer.Line();
            }
        }
Ejemplo n.º 2
0
        private void WriteStartOperationOperation(CodeWriter writer, LongRunningOperationMethod lroMethod, bool async)
        {
            RestClientMethod originalMethod = lroMethod.StartMethod;
            CSharpType       returnType     = async ? new CSharpType(typeof(Task <>), lroMethod.Operation.Type) : lroMethod.Operation.Type;

            Parameter[] parameters = originalMethod.Parameters;

            writer.WriteXmlDocumentationSummary(originalMethod.Description);

            foreach (Parameter parameter in parameters)
            {
                writer.WriteXmlDocumentationParameter(parameter.Name, parameter.Description);
            }
            writer.WriteXmlDocumentationParameter("cancellationToken", "The cancellation token to use.");

            string asyncText = async ? "async " : string.Empty;

            writer.Append($"public virtual {asyncText}{returnType} {CreateStartOperationName(lroMethod.Name, async)}(");
            foreach (Parameter parameter in parameters)
            {
                writer.WriteParameter(parameter);
            }
            writer.Line($"{typeof(CancellationToken)} cancellationToken = default)");

            using (writer.Scope())
            {
                writer.WriteParameterNullChecks(parameters);

                WriteDiagnosticScope(writer, lroMethod.Diagnostics, writer =>
                {
                    string awaitText     = async ? "await" : string.Empty;
                    string configureText = async ? ".ConfigureAwait(false)" : string.Empty;
                    writer.Append($"var originalResponse = {awaitText} RestClient.{CreateMethodName(originalMethod.Name, async)}(");
                    foreach (Parameter parameter in parameters)
                    {
                        writer.Append($"{parameter.Name}, ");
                    }

                    writer.Line($"cancellationToken){configureText};");

                    writer.Append($"return new {lroMethod.Operation.Type}({ClientDiagnosticsField}, {PipelineField}, RestClient.{CreateRequestMethodName(originalMethod.Name)}(");
                    foreach (Parameter parameter in parameters)
                    {
                        writer.Append($"{parameter.Name}, ");
                    }
                    writer.RemoveTrailingComma();
                    writer.Line($").Request, originalResponse);");
                });
            }
            writer.Line();
        }
Ejemplo n.º 3
0
        private void WriteClientCtors(CodeWriter writer, Client client)
        {
            writer.WriteXmlDocumentationSummary($"Initializes a new instance of {client.Type.Name} for mocking.");
            using (writer.Scope($"protected {client.Type.Name:D}()"))
            {
            }

            writer.WriteXmlDocumentationSummary($"Initializes a new instance of {client.Type.Name}");
            writer.WriteXmlDocumentationParameter(ClientDiagnosticsVariable, "The handler for diagnostic messaging in the client.");
            writer.WriteXmlDocumentationParameter(PipelineVariable, "The HTTP pipeline for sending and receiving REST requests and responses.");
            foreach (Parameter parameter in client.RestClient.Parameters)
            {
                writer.WriteXmlDocumentationParameter(parameter.Name, parameter.Description);
            }

            writer.Append($"internal {client.Type.Name:D}({typeof(ClientDiagnostics)} {ClientDiagnosticsVariable}, {typeof(HttpPipeline)} {PipelineVariable},");
            foreach (Parameter parameter in client.RestClient.Parameters)
            {
                writer.WriteParameter(parameter);
            }

            writer.RemoveTrailingComma();
            writer.Line($")");
            using (writer.Scope())
            {
                writer.Append($"this.RestClient = new {client.RestClient.Type}({ClientDiagnosticsVariable}, {PipelineVariable}, ");
                foreach (var parameter in client.RestClient.Parameters)
                {
                    writer.Append($"{parameter.Name}, ");
                }
                writer.RemoveTrailingComma();
                writer.Line($");");

                writer.Line($"{ClientDiagnosticsField} = {ClientDiagnosticsVariable};");
                writer.Line($"{PipelineField} = {PipelineVariable};");
            }
            writer.Line();
        }
Ejemplo n.º 4
0
        private void WriteSealedChoiceSchema(CodeWriter writer, EnumType schema)
        {
            if (schema.Declaration.IsUserDefined)
            {
                return;
            }

            using (writer.Namespace(schema.Declaration.Namespace))
            {
                writer.WriteXmlDocumentationSummary(schema.Description);

                using (writer.Scope($"public enum {schema.Declaration.Name}"))
                {
                    foreach (EnumTypeValue value in schema.Values)
                    {
                        writer.WriteXmlDocumentationSummary(value.Description);
                        writer.Line($"{value.Declaration.Name},");
                    }
                    writer.RemoveTrailingComma();
                }
            }
        }
        private void WriteClientCtor(CodeWriter writer, RestClient restClient, CSharpType cs)
        {
            writer.WriteXmlDocumentationSummary($"Initializes a new instance of {cs.Name}");
            writer.WriteXmlDocumentationParameter(ClientDiagnosticsVariable, "The handler for diagnostic messaging in the client.");
            writer.WriteXmlDocumentationParameter(PipelineVariable, "The HTTP pipeline for sending and receiving REST requests and responses.");
            foreach (Parameter parameter in restClient.Parameters)
            {
                writer.WriteXmlDocumentationParameter(parameter.Name, parameter.Description);
            }
            if (restClient.Parameters.HasAnyNullCheck())
            {
                writer.WriteXmlDocumentationException(typeof(ArgumentNullException), "This occurs when one of the required arguments is null.");
            }

            writer.Append($"public {cs.Name:D}({typeof(ClientDiagnostics)} {ClientDiagnosticsVariable}, {typeof(HttpPipeline)} {PipelineVariable},");
            foreach (Parameter clientParameter in restClient.Parameters)
            {
                writer.WriteParameter(clientParameter);
            }

            writer.RemoveTrailingComma();
            writer.Line($")");
            using (writer.Scope())
            {
                writer.WriteParameterNullChecks(restClient.Parameters);

                foreach (Parameter clientParameter in restClient.Parameters)
                {
                    writer.Line($"this.{clientParameter.Name} = {clientParameter.Name};");
                }

                writer.Line($"{ClientDiagnosticsField} = {ClientDiagnosticsVariable};");
                writer.Line($"{PipelineField} = {PipelineVariable};");
            }
            writer.Line();
        }
        public static void WriteAggregateClient(CodeWriter writer, BuildContext context)
        {
            var title = context.Configuration.LibraryName;

            using (writer.Scope($"namespace {context.Configuration.Namespace}"))
            {
                Dictionary <string, Parameter> allParameters = new Dictionary <string, Parameter>();
                foreach (var parameter in context.Library.Clients.SelectMany(p => p.RestClient.Parameters))
                {
                    if (ManagementClientWriterHelpers.IsApiVersionParameter(parameter))
                    {
                        continue;
                    }

                    allParameters[parameter.Name] = parameter;
                }

                writer.WriteXmlDocumentationSummary($"{title} service management client.");
                using (writer.Scope($"public class {title}ManagementClient"))
                {
                    writer.Line($"private readonly {typeof(ClientDiagnostics)}  {ClientDiagnosticsField};");
                    writer.Line($"private readonly {typeof(HttpPipeline)} {PipelineField};");
                    foreach (var parameter in allParameters.Values)
                    {
                        writer.Line($"private readonly {parameter.Type} _{parameter.Name};");
                    }

                    writer.Line();

                    writer.WriteXmlDocumentationSummary($"Initializes a new instance of {title}ManagementClient for mocking.");
                    using (writer.Scope($"protected {title}ManagementClient()"))
                    {
                    }
                    writer.Line();


                    writer.WriteXmlDocumentationSummary($"Initializes a new instance of {title}ManagementClient");
                    foreach (Parameter parameter in allParameters.Values)
                    {
                        if (ManagementClientWriterHelpers.IsEndpointParameter(parameter))
                        {
                            continue;
                        }
                        writer.WriteXmlDocumentationParameter(parameter.Name, parameter.Description);
                    }
                    writer.WriteXmlDocumentationParameter(TokenCredentialVariable, "The OAuth token for making client requests.");
                    writer.WriteXmlDocumentationParameter(OptionsVariable, "The options for configuring the client.");

                    writer.Append($"public {title}ManagementClient(");
                    foreach (Parameter parameter in allParameters.Values)
                    {
                        if (ManagementClientWriterHelpers.IsEndpointParameter(parameter))
                        {
                            continue;
                        }

                        writer.WriteParameter(parameter);
                    }

                    writer.Append($"{typeof(TokenCredential)} {TokenCredentialVariable}, {title}ManagementClientOptions {OptionsVariable} = null) : this(");
                    foreach (Parameter parameter in allParameters.Values)
                    {
                        // Pass the default host
                        if (ManagementClientWriterHelpers.IsEndpointParameter(parameter))
                        {
                            writer.Append($"null, ");
                            continue;
                        }

                        writer.Append($"{parameter.Name},");
                    }

                    writer.Line($"{TokenCredentialVariable}, {OptionsVariable})");
                    using (writer.Scope())
                    {
                    }

                    writer.WriteXmlDocumentationSummary($"Initializes a new instance of {title}ManagementClient");
                    foreach (Parameter parameter in allParameters.Values)
                    {
                        writer.WriteXmlDocumentationParameter(parameter.Name, parameter.Description);
                    }
                    writer.WriteXmlDocumentationParameter(TokenCredentialVariable, "The OAuth token for making client requests.");
                    writer.WriteXmlDocumentationParameter(OptionsVariable, "The options for configuring the client.");
                    if (allParameters.Values.HasAnyNullCheck())
                    {
                        writer.WriteXmlDocumentationException(typeof(ArgumentNullException), "This occurs when one of the required arguments is null.");
                    }

                    writer.Append($"public {title}ManagementClient(");
                    foreach (Parameter parameter in allParameters.Values)
                    {
                        writer.WriteParameter(parameter, false);
                    }

                    writer.Append($"{typeof(TokenCredential)} {TokenCredentialVariable}, {title}ManagementClientOptions {OptionsVariable} = null)");

                    using (writer.Scope())
                    {
                        writer.WriteParameterNullChecks(allParameters.Values);

                        writer.Line($"{OptionsVariable} ??= new {title}ManagementClientOptions();");
                        writer.Line($"{ClientDiagnosticsField} = new {typeof(ClientDiagnostics)}({OptionsVariable});");
                        writer.Line($"{PipelineField} = {typeof(ManagementPipelineBuilder)}.Build({TokenCredentialVariable}, endpoint, {OptionsVariable});");

                        foreach (Parameter parameter in allParameters.Values)
                        {
                            writer.Line($"_{parameter.Name} = {parameter.Name};");
                        }
                    }
                    writer.Line();

                    foreach (var client in context.Library.Clients)
                    {
                        writer.WriteXmlDocumentationSummary($"Creates a new instance of {client.Type.Name}");
                        using (writer.Scope($"public virtual {client.Type} Get{client.Type.Name}()"))
                        {
                            writer.Append($"return new {client.Type}({ClientDiagnosticsField}, {PipelineField}, ");
                            foreach (var parameter in client.RestClient.Parameters)
                            {
                                if (ManagementClientWriterHelpers.IsApiVersionParameter(parameter))
                                {
                                    continue;
                                }

                                writer.Append($"_{parameter.Name}, ");
                            }
                            writer.RemoveTrailingComma();
                            writer.Line($");");
                        }

                        writer.Line();
                    }
                }
            }
        }
Ejemplo n.º 7
0
        public static CodeWriter WriteInitialization(this CodeWriter writer, ObjectType objectType, IEnumerable <ObjectPropertyInitializer> initializers)
        {
            ObjectPropertyInitializer?FindInitializerForParameter(ObjectTypeConstructor constructor, Parameter constructorParameter)
            {
                var property = constructor.FindPropertyInitializedByParameter(constructorParameter);

                return(initializers.SingleOrDefault(i => i.Property == property));
            }

            // Checks if constructor parameters can be satisfied by the provided initializer list
            List <ObjectPropertyInitializer>?TryGetParameters(ObjectTypeConstructor constructor)
            {
                List <ObjectPropertyInitializer> constructorInitializers = new List <ObjectPropertyInitializer>();

                foreach (var constructorParameter in constructor.Parameters)
                {
                    var objectPropertyInitializer = FindInitializerForParameter(constructor, constructorParameter);
                    if (objectPropertyInitializer == null)
                    {
                        return(null);
                    }

                    constructorInitializers.Add(objectPropertyInitializer);
                }

                return(constructorInitializers);
            }

            // Find longest satisfiable ctor
            List <ObjectPropertyInitializer>?selectedCtorInitializers = null;

            foreach (var constructor in objectType.Constructors)
            {
                var newInitializers = TryGetParameters(constructor);
                if (newInitializers != null &&
                    newInitializers.Count > (selectedCtorInitializers?.Count ?? -1))
                {
                    selectedCtorInitializers = newInitializers;
                }
            }

            Debug.Assert(selectedCtorInitializers != null);

            writer.Append($"new {objectType.Type}(");
            foreach (var initializer in selectedCtorInitializers)
            {
                writer.WriteReferenceOrConstant(initializer.Value);
                writer.WriteConversion(initializer.Value.Type, initializer.Property.Declaration.Type);
                writer.Append($", ");
            }
            writer.RemoveTrailingComma();
            writer.Append($")");

            // Find properties that would have to be initialized via property initializers
            var restOfInitializers = initializers.Except(selectedCtorInitializers).ToArray();

            if (restOfInitializers.Any())
            {
                using (writer.Scope($"", newLine: false))
                {
                    foreach (var propertyInitializer in restOfInitializers)
                    {
                        writer.Append($"{propertyInitializer.Property.Declaration.Name} = ")
                        .WriteReferenceOrConstant(propertyInitializer.Value);

                        writer.WriteConversion(propertyInitializer.Value.Type, propertyInitializer.Property.Declaration.Type);

                        writer.Line($",");
                    }

                    writer.RemoveTrailingComma();
                }
            }

            return(writer);
        }
        private void WriteRequestCreation(CodeWriter writer, RestClientMethod clientMethod)
        {
            using var methodScope = writer.AmbientScope();

            var methodName = CreateRequestMethodName(clientMethod.Name);

            writer.Append($"internal {typeof(HttpMessage)} {methodName}(");
            var parameters = clientMethod.Parameters;

            foreach (Parameter clientParameter in parameters)
            {
                writer.Append($"{clientParameter.Type} {clientParameter.Name:D},");
            }
            writer.RemoveTrailingComma();
            writer.Line($")");
            using (writer.Scope())
            {
                var message = new CodeWriterDeclaration("message");
                var request = new CodeWriterDeclaration("request");
                var uri     = new CodeWriterDeclaration("uri");

                writer.Line($"var {message:D} = {PipelineField}.CreateMessage();");
                writer.Line($"var {request:D} = {message}.Request;");
                var method = clientMethod.Request.HttpMethod;
                writer.Line($"{request}.Method = {typeof(RequestMethod)}.{method.ToRequestMethodName()};");

                writer.Line($"var {uri:D} = new RawRequestUriBuilder();");
                foreach (var segment in clientMethod.Request.PathSegments)
                {
                    if (!segment.Value.IsConstant && segment.Value.Reference.Name == "nextLink")
                    {
                        if (segment.IsRaw)
                        {
                            // Artificial nextLink needs additional logic for relative versus absolute links
                            WritePathSegment(writer, uri, segment, "AppendRawNextLink");
                        }
                        else
                        {
                            // Natural nextLink parameters need to use a different method to parse path and query elements
                            WritePathSegment(writer, uri, segment, "AppendRaw");
                        }
                    }
                    else
                    {
                        WritePathSegment(writer, uri, segment);
                    }
                }

                //TODO: Duplicate code between query and header parameter processing logic
                foreach (var queryParameter in clientMethod.Request.Query)
                {
                    WriteQueryParameter(writer, uri, queryParameter);
                }

                writer.Line($"{request}.Uri = {uri};");

                foreach (var header in clientMethod.Request.Headers)
                {
                    WriteHeader(writer, request, header);
                }

                switch (clientMethod.Request.Body)
                {
                case SchemaRequestBody body:
                    using (WriteValueNullCheck(writer, body.Value))
                    {
                        WriteSerializeContent(
                            writer,
                            request,
                            body.Serialization,
                            w => WriteConstantOrParameter(w, body.Value, ignoreNullability: true));
                    }

                    break;

                case BinaryRequestBody binaryBody:
                    using (WriteValueNullCheck(writer, binaryBody.Value))
                    {
                        writer.Append($"{request}.Content = {typeof(RequestContent)}.Create(");
                        WriteConstantOrParameter(writer, binaryBody.Value);
                        writer.Line($");");
                    }
                    break;

                case TextRequestBody textBody:
                    using (WriteValueNullCheck(writer, textBody.Value))
                    {
                        writer.Append($"{request}.Content = new {typeof(StringRequestContent)}(");
                        WriteConstantOrParameter(writer, textBody.Value);
                        writer.Line($");");
                    }
                    break;

                case FlattenedSchemaRequestBody flattenedSchemaRequestBody:
                    var modelVariable = new CodeWriterDeclaration("model");
                    writer.Append($"var {modelVariable:D} = ")
                    .WriteInitialization(flattenedSchemaRequestBody.ObjectType, flattenedSchemaRequestBody.Initializers)
                    .Line($";");

                    WriteSerializeContent(
                        writer,
                        request,
                        flattenedSchemaRequestBody.Serialization,
                        w => w.Append(modelVariable));
                    break;

                case null:
                    break;

                default:
                    throw new NotImplementedException(clientMethod.Request.Body?.GetType().FullName);
                }

                writer.Line($"return {message};");
            }
            writer.Line();
        }
Ejemplo n.º 9
0
        private void WriteObjectSerialization(CodeWriter writer, ObjectType model)
        {
            if (!model.Serializations.Any())
            {
                return;
            }

            using (writer.Namespace(model.Declaration.Namespace))
            {
                if (model.IsStruct)
                {
                    writer.Append($"{model.Declaration.Accessibility} partial struct {model.Declaration.Name}");
                }
                else
                {
                    writer.Append($"{model.Declaration.Accessibility} partial class {model.Declaration.Name}");
                }

                if (model.IncludeSerializer)
                {
                    bool hasJson = model.Serializations.OfType <JsonSerialization>().Any();
                    bool hasXml  = model.Serializations.OfType <XmlElementSerialization>().Any();
                    if (hasJson || hasXml)
                    {
                        writer.Append($": ");
                    }

                    if (hasJson)
                    {
                        writer.Append($"{typeof(IUtf8JsonSerializable)}");
                        writer.Append($", ");
                    }

                    if (hasXml)
                    {
                        writer.Append($"{typeof(IXmlSerializable)}");
                        writer.Append($", ");
                    }

                    writer.RemoveTrailingComma();
                }

                using (writer.Scope())
                {
                    foreach (var serialization in model.Serializations)
                    {
                        switch (serialization)
                        {
                        case JsonSerialization jsonSerialization:
                            if (model.IncludeSerializer)
                            {
                                WriteJsonSerialize(writer, jsonSerialization);
                            }

                            if (model.IncludeDeserializer)
                            {
                                WriteJsonDeserialize(writer, model, jsonSerialization);
                            }

                            break;

                        case XmlElementSerialization xmlSerialization:
                            if (model.IncludeSerializer)
                            {
                                WriteXmlSerialize(writer, xmlSerialization);
                            }

                            if (model.IncludeDeserializer)
                            {
                                WriteXmlDeserialize(writer, model, xmlSerialization);
                            }

                            break;

                        default:
                            throw new NotImplementedException(serialization.ToString());
                        }
                    }
                }
            }
        }
Ejemplo n.º 10
0
        private void WriteObjectSchema(CodeWriter writer, ObjectType schema)
        {
            using (writer.Namespace(schema.Declaration.Namespace))
            {
                List <CSharpType> implementsTypes = new List <CSharpType>();
                if (schema.Inherits != null)
                {
                    implementsTypes.Add(schema.Inherits);
                }

                if (schema.ImplementsDictionaryType != null)
                {
                    implementsTypes.Add(schema.ImplementsDictionaryType);
                }

                writer.WriteXmlDocumentationSummary(schema.Description);

                if (schema.IsStruct)
                {
                    writer.Append($"{schema.Declaration.Accessibility} readonly partial struct {schema.Declaration.Name}");
                }
                else
                {
                    writer.Append($"{schema.Declaration.Accessibility} partial class {schema.Declaration.Name}");
                }

                if (implementsTypes.Any())
                {
                    writer.AppendRaw(" : ");
                    foreach (var type in implementsTypes)
                    {
                        writer.Append($"{type} ,");
                    }
                    writer.RemoveTrailingComma();
                }

                writer.Line();
                using (writer.Scope())
                {
                    WriteConstructor(writer, schema);

                    foreach (var property in schema.Properties)
                    {
                        writer.WriteXmlDocumentationSummary(property.Description);

                        CSharpType propertyType = property.Declaration.Type;
                        writer.Append($"{property.Declaration.Accessibility} {propertyType} {property.Declaration.Name:D}");
                        writer.AppendRaw(property.IsReadOnly ? "{ get; }" : "{ get; set; }");

                        writer.Line();
                    }

                    if (schema.AdditionalPropertiesProperty is ObjectTypeProperty additionalPropertiesProperty)
                    {
                        var dictionaryType = schema.ImplementsDictionaryType;
                        Debug.Assert(dictionaryType != null);

                        var keyType                     = typeof(string);
                        var isReadonly                  = dictionaryType.FrameworkType == typeof(IReadOnlyDictionary <,>);
                        var itemType                    = dictionaryType.Arguments[1];
                        var keyValuePairType            = new CSharpType(typeof(KeyValuePair <,>), keyType, itemType);
                        var iEnumeratorKeyValuePairType = new CSharpType(typeof(IEnumerator <>), keyValuePairType);

                        var collectionType = isReadonly ? typeof(IReadOnlyCollection <>) : typeof(ICollection <>);

                        var iCollectionKeyValuePairType = new CSharpType(collectionType, keyValuePairType);

                        var keyValueCollectionType = isReadonly ? typeof(IEnumerable <>) : typeof(ICollection <>);
                        var iCollectionKeyType     = new CSharpType(keyValueCollectionType, keyType);
                        var iCollectionItemType    = new CSharpType(keyValueCollectionType, itemType);
                        var iEnumerator            = typeof(IEnumerator);
                        var iEnumerable            = typeof(IEnumerable);

                        string additionalProperties = additionalPropertiesProperty.Declaration.Name;

                        writer
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"public {iEnumeratorKeyValuePairType} GetEnumerator() => {additionalProperties}.GetEnumerator();")
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"{iEnumerator} {iEnumerable}.GetEnumerator() => {additionalProperties}.GetEnumerator();")
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"public bool TryGetValue(string key, out {itemType} value) => {additionalProperties}.TryGetValue(key, out value);")
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"public bool ContainsKey({keyType} key) => {additionalProperties}.ContainsKey(key);")
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"public {iCollectionKeyType} Keys => {additionalProperties}.Keys;")
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"public {iCollectionItemType} Values => {additionalProperties}.Values;")
                        .WriteXmlDocumentationInheritDoc()
                        .Line($"int {iCollectionKeyValuePairType}.Count => {additionalProperties}.Count;");

                        if (!isReadonly)
                        {
                            writer
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"public void Add({keyType} key, {itemType} value) => {additionalProperties}.Add(key, value);")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"public bool Remove({keyType} key) => {additionalProperties}.Remove(key);")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"bool {iCollectionKeyValuePairType}.IsReadOnly => {additionalProperties}.IsReadOnly;")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"void {iCollectionKeyValuePairType}.Add({keyValuePairType} value) => {additionalProperties}.Add(value);")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"bool {iCollectionKeyValuePairType}.Remove({keyValuePairType} value) => {additionalProperties}.Remove(value);")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"bool {iCollectionKeyValuePairType}.Contains({keyValuePairType} value) => {additionalProperties}.Contains(value);")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"void {iCollectionKeyValuePairType}.CopyTo({keyValuePairType}[] destination, int offset) => {additionalProperties}.CopyTo(destination, offset);")
                            .WriteXmlDocumentationInheritDoc()
                            .Line($"void {iCollectionKeyValuePairType}.Clear() => {additionalProperties}.Clear();");
                        }

                        using (writer
                               .WriteXmlDocumentationInheritDoc()
                               .Scope($"public {itemType} this[{keyType} key]"))
                        {
                            writer.Line($"get => {additionalProperties}[key];");
                            if (!isReadonly)
                            {
                                writer.Line($"set => {additionalProperties}[key] = value;");
                            }
                        }
                    }
                }
            }
        }