public string GeneratePartialClassFor(ApiDto apiDto)
        {
            var indent  = new Indent();
            var builder = new StringBuilder();

            var typeNameForDto        = apiDto.ToCSharpClassName();
            var typeNameForPartialDto = $"Partial<{typeNameForDto}>";

            builder.AppendLine($"{indent}public static class {typeNameForDto}PartialExtensions");
            builder.AppendLine($"{indent}{{");
            indent.Increment();

            foreach (var apiDtoField in apiDto.Fields)
            {
                builder.Append(indent.Wrap(GenerateExtensionMethodsFor(typeNameForDto, typeNameForPartialDto, apiDtoField.Field)));
            }

            indent.Decrement();
            builder.AppendLine($"{indent}}}");
            return(builder.ToString());
        }
Ejemplo n.º 2
0
        public string GenerateDtoDefinition(ApiDto apiDto)
        {
            var indent  = new Indent();
            var builder = new StringBuilder();

            var typeNameForDto = apiDto.ToCSharpClassName();

            if (apiDto.Deprecation != null)
            {
                builder.AppendLine(apiDto.Deprecation.ToCSharpDeprecation());
            }

            if (apiDto.HierarchyRole != HierarchyRole.INTERFACE && apiDto.Extends == null && apiDto.Inheritors.Count > 0)
            {
                // When extending another DTO, make sure to apply a converter
                builder.AppendLine($"{indent}[JsonConverter(typeof(ClassNameDtoTypeConverter))]");
            }

            var modifierForDto = apiDto.HierarchyRole == HierarchyRole.INTERFACE
                ? "interface"
                : apiDto.HierarchyRole == HierarchyRole.ABSTRACT
                    ? "abstract class"
                    : apiDto.HierarchyRole == HierarchyRole.FINAL
                        ? "sealed class"
                        : "class";

            var dtoHierarchy           = new List <string>();
            var dtoHierarchyFieldNames = new List <string>();

            if (apiDto.Extends != null && _codeGenerationContext.TryGetDto(apiDto.Extends.Id, out var apiDtoExtends))
            {
                dtoHierarchy.Add(apiDtoExtends !.ToCSharpClassName());
                dtoHierarchyFieldNames.AddRange(apiDtoExtends !.Fields.Select(it => it.Field.Name));
            }
            if (apiDto.Implements != null)
            {
                foreach (var dtoImplements in apiDto.Implements)
                {
                    if (_codeGenerationContext.TryGetDto(dtoImplements.Id, out var apiDtoImplements))
                    {
                        dtoHierarchy.Add(apiDtoImplements !.ToCSharpClassName());
                    }
                }
            }
            if (dtoHierarchy.Count > 0 || apiDto.Inheritors.Count > 0)
            {
                dtoHierarchy.Add(nameof(IClassNameConvertible));
            }

            dtoHierarchy.Add(nameof(IPropagatePropertyAccessPath));

            builder.AppendLine($"{indent}public {modifierForDto} {typeNameForDto}");
            indent.Increment();
            builder.AppendLine($"{indent} : " + string.Join(", ", dtoHierarchy));
            indent.Decrement();

            builder.AppendLine($"{indent}{{");
            indent.Increment();

            // When in a hierarchy with IClassNameConvertible, make sure we can capture the class name.
            if (dtoHierarchy.Contains(nameof(IClassNameConvertible)) && apiDto.HierarchyRole != HierarchyRole.INTERFACE)
            {
                var modifierForClassNameProperty = apiDto.Extends == null
                    ? apiDto.HierarchyRole != HierarchyRole.FINAL
                        ? "virtual" // Parent
                        : ""
                    : "override";   // Inheritor

                builder.AppendLine($"{indent}[JsonPropertyName(\"className\")]");
                builder.AppendLine($"{indent}public {modifierForClassNameProperty} string? ClassName => \"{apiDto.Name}\";");
                builder.AppendLine($"{indent}");
            }

            // Determine list of fields
            var apiDtoFields = DetermineFieldsToGenerateFor(apiDto);

            // Generate factories for inheritors
            foreach (var apiDtoInheritorReference in apiDto.Inheritors)
            {
                if (_codeGenerationContext.TryGetDto(apiDtoInheritorReference.Id, out var apiDtoInheritor) &&
                    apiDtoInheritor !.HierarchyRole != HierarchyRole.INTERFACE && apiDtoInheritor.HierarchyRole != HierarchyRole.ABSTRACT)
                {
                    var inheritorTypeName          = apiDtoInheritor.ToCSharpClassName();
                    var inheritorFactoryMethodName = apiDtoInheritor.ToCSharpFactoryMethodName(apiDto);

                    var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                                                  .WithParametersForApiDtoFields(DetermineFieldsToGenerateFor(apiDtoInheritor !));

                    builder.AppendLine($"{indent}public static {inheritorTypeName} {inheritorFactoryMethodName}({methodParametersBuilder.BuildMethodParametersList()})");
                    indent.Increment();
                    builder.AppendLine($"{indent}=> new {inheritorTypeName}({methodParametersBuilder.WithDefaultValueForAllParameters(null).BuildMethodCallParameters()});");
                    indent.Decrement();
                    builder.AppendLine($"{indent}");
                }
            }

            // Generate constructor
            // ReSharper disable once RedundantLogicalConditionalExpressionOperand
            if (apiDto.HierarchyRole != HierarchyRole.INTERFACE && apiDto.HierarchyRole != HierarchyRole.ABSTRACT)
            {
                var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                                              .WithParametersForApiDtoFields(apiDtoFields);

                // Empty constructor
                builder.AppendLine($"{indent}public {typeNameForDto}() {{ }}");
                builder.AppendLine($"{indent}");

                // Parameterized constructor
                if (apiDtoFields.Count > 0)
                {
                    builder.AppendLine($"{indent}public {typeNameForDto}({methodParametersBuilder.BuildMethodParametersList()})");
                    builder.AppendLine($"{indent}{{");
                    indent.Increment();
                    foreach (var apiDtoField in apiDtoFields)
                    {
                        if (FeatureFlags.GenerateAlternativeForOptionalParameterDefaultReferenceTypes && apiDtoField.Field.Type.IsCSharpReferenceType())
                        {
                            builder.AppendLine($"{indent}{apiDtoField.Field.ToCSharpPropertyName(typeNameForDto)} = {apiDtoField.Field.ToCSharpVariableInstanceOrDefaultValue(_codeGenerationContext)};");
                        }
                        else
                        {
                            builder.AppendLine($"{indent}{apiDtoField.Field.ToCSharpPropertyName(typeNameForDto)} = {apiDtoField.Field.ToCSharpVariableName()};");
                        }
                    }
                    indent.Decrement();
                    builder.AppendLine($"{indent}}}");
                    builder.AppendLine($"{indent}");
                }
            }

            // Generate properties for fields
            foreach (var apiDtoField in apiDtoFields)
            {
                builder.AppendLine(indent.Wrap(GenerateDtoFieldDefinition(typeNameForDto, apiDtoField.Field)));
            }

            // Implement IPropagatePropertyAccessPath?
            if (dtoHierarchy.Contains(nameof(IPropagatePropertyAccessPath)) && apiDto.HierarchyRole != HierarchyRole.INTERFACE)
            {
                builder.AppendLine(indent.Wrap(GenerateDtoPropagatePropertyAccessPath(apiDto, apiDtoFields)));
            }

            indent.Decrement();
            builder.AppendLine($"{indent}}}");
            return(builder.ToString());
        }