From e41fd2d815fe72e4756bea481fe47892c2df1f7c Mon Sep 17 00:00:00 2001 From: CodeLiturgy Date: Thu, 18 Aug 2022 16:46:20 +0100 Subject: [PATCH] Adapt data to new MapTo feature --- .../Controllers/CountriesController.cs | 12 +- .../Controllers/CurrenciesController.cs | 25 +- .../{Finance/Currency => Country}/Country.cs | 0 .../Currency => Country}/CountryCreate.cs | 0 .../Currency => Country}/CountryUpdate.cs | 0 .../{Finance => }/Currency/Currency.cs | 8 +- .../{Finance => }/Currency/CurrencyCreate.cs | 0 .../{Finance => }/Currency/CurrencyUpdate.cs | 3 +- .../{Finance => }/Currency/TestData.cs | 0 .../Transaction/FinanceTransaction.cs | 0 .../FinanceTransactionInsertDto.cs | 0 .../Transaction/FinanceTransactionReadDto.cs | 0 .../Transaction/FinanceTransactionType.cs | 0 .../Extensions/CommonExtensions.cs | 28 +- .../BlueWest.MapTo/Extensions/CommonSource.cs | 265 ++++++++++-------- .../BlueWest.MapTo/Sources/MapRecordSource.cs | 228 ++++++++------- 16 files changed, 336 insertions(+), 233 deletions(-) rename BlueWest.Data/{Finance/Currency => Country}/Country.cs (100%) rename BlueWest.Data/{Finance/Currency => Country}/CountryCreate.cs (100%) rename BlueWest.Data/{Finance/Currency => Country}/CountryUpdate.cs (100%) rename BlueWest.Data/{Finance => }/Currency/Currency.cs (57%) rename BlueWest.Data/{Finance => }/Currency/CurrencyCreate.cs (100%) rename BlueWest.Data/{Finance => }/Currency/CurrencyUpdate.cs (64%) rename BlueWest.Data/{Finance => }/Currency/TestData.cs (100%) rename BlueWest.Data/{Finance => }/Transaction/FinanceTransaction.cs (100%) rename BlueWest.Data/{Finance => }/Transaction/FinanceTransactionInsertDto.cs (100%) rename BlueWest.Data/{Finance => }/Transaction/FinanceTransactionReadDto.cs (100%) rename BlueWest.Data/{Finance => }/Transaction/FinanceTransactionType.cs (100%) diff --git a/BlueWest.Api/Controllers/CountriesController.cs b/BlueWest.Api/Controllers/CountriesController.cs index 57a9a81..4f4aa2e 100644 --- a/BlueWest.Api/Controllers/CountriesController.cs +++ b/BlueWest.Api/Controllers/CountriesController.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using BlueWest.Data; using BlueWest.WebApi.MySQL; @@ -6,6 +7,9 @@ using Microsoft.AspNetCore.Mvc; namespace BlueWest.WebApi.Controllers { +/// +/// Controller responsible to get country data +/// [ApiController] [Route("[controller]")] public class CountriesController : ControllerBase @@ -25,7 +29,7 @@ public class CountriesController : ControllerBase /// /// Add Country /// - /// + /// The country data to create /// The newly created country /// /// /// Creates a Country. @@ -44,11 +48,11 @@ public class CountriesController : ControllerBase /// Returns the newly created country [ProducesResponseType(StatusCodes.Status201Created)] [HttpPost] - public ActionResult AddCountry(Country country) + public ActionResult AddCountry(CountryCreate countryToCreate) { - _dbContext.Countries.Add(country); + _dbContext.Countries.Add(new Country(countryToCreate, new List())); _dbContext.SaveChanges(); - return CreatedAtRoute(nameof(GetCountryById), new {countryId = country.Code}, country); + return CreatedAtRoute(nameof(GetCountryById), new {countryId = countryToCreate.Code}, countryToCreate); } /// diff --git a/BlueWest.Api/Controllers/CurrenciesController.cs b/BlueWest.Api/Controllers/CurrenciesController.cs index 661a09a..d22fad3 100644 --- a/BlueWest.Api/Controllers/CurrenciesController.cs +++ b/BlueWest.Api/Controllers/CurrenciesController.cs @@ -7,6 +7,9 @@ using Microsoft.AspNetCore.Mvc; namespace BlueWest.WebApi.Controllers { + /// + /// The controller responsible to fetch currency data + /// [ApiController] [Route("[controller]")] public class CurrenciesController : ControllerBase @@ -19,16 +22,27 @@ namespace BlueWest.WebApi.Controllers } + /// + /// Add Currency to the table of currencies + /// + /// Currency data to create + /// [ProducesResponseType(StatusCodes.Status201Created)] [HttpPost] - public ActionResult AddCurrency(CurrencyCreate currency) + public ActionResult AddCurrency(CurrencyCreate currencyToCreate) { - var newCurrency = new Currency(); + var newCurrency = new Currency(currencyToCreate, new List()); _dbContext.Currencies.Add(newCurrency); _dbContext.SaveChanges(); - return CreatedAtRoute(nameof(GetCurrencyById), new {CurrencyId = currency.Code}, currency); + return CreatedAtRoute(nameof(GetCurrencyById), new {CurrencyId = currencyToCreate.Code}, currencyToCreate); } + /// + /// Update a currency data from the Currency table in the database + /// + /// The currency number we want to update + /// Currency Data to update + /// [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [HttpPut("{currencyNumber}")] @@ -48,6 +62,11 @@ namespace BlueWest.WebApi.Controllers } + /// + /// Gets a currency by the currency number (id) + /// + /// The id of the currency to get + /// [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [HttpGet("{currencyId}", Name = nameof(GetCurrencyById))] diff --git a/BlueWest.Data/Finance/Currency/Country.cs b/BlueWest.Data/Country/Country.cs similarity index 100% rename from BlueWest.Data/Finance/Currency/Country.cs rename to BlueWest.Data/Country/Country.cs diff --git a/BlueWest.Data/Finance/Currency/CountryCreate.cs b/BlueWest.Data/Country/CountryCreate.cs similarity index 100% rename from BlueWest.Data/Finance/Currency/CountryCreate.cs rename to BlueWest.Data/Country/CountryCreate.cs diff --git a/BlueWest.Data/Finance/Currency/CountryUpdate.cs b/BlueWest.Data/Country/CountryUpdate.cs similarity index 100% rename from BlueWest.Data/Finance/Currency/CountryUpdate.cs rename to BlueWest.Data/Country/CountryUpdate.cs diff --git a/BlueWest.Data/Finance/Currency/Currency.cs b/BlueWest.Data/Currency/Currency.cs similarity index 57% rename from BlueWest.Data/Finance/Currency/Currency.cs rename to BlueWest.Data/Currency/Currency.cs index 55cbabf..5d95c36 100644 --- a/BlueWest.Data/Finance/Currency/Currency.cs +++ b/BlueWest.Data/Currency/Currency.cs @@ -4,12 +4,14 @@ using MapTo; namespace BlueWest.Data { - [MapFrom(typeof(CurrencyUpdate))] + [MapFrom(new []{ + typeof(CurrencyUpdate), + typeof(CurrencyCreate)})] public partial class Currency { - [MaxLength(3)]public int Num { get; set; } // Primary key - [MaxLength(3)]public string Code { get; set; } + [MaxLength(3)] public int Num { get; set; } // Primary key + [MaxLength(3)] public string Code { get; set; } public List Countries { get; set; } public Currency() diff --git a/BlueWest.Data/Finance/Currency/CurrencyCreate.cs b/BlueWest.Data/Currency/CurrencyCreate.cs similarity index 100% rename from BlueWest.Data/Finance/Currency/CurrencyCreate.cs rename to BlueWest.Data/Currency/CurrencyCreate.cs diff --git a/BlueWest.Data/Finance/Currency/CurrencyUpdate.cs b/BlueWest.Data/Currency/CurrencyUpdate.cs similarity index 64% rename from BlueWest.Data/Finance/Currency/CurrencyUpdate.cs rename to BlueWest.Data/Currency/CurrencyUpdate.cs index 39cd1f6..d9f9828 100644 --- a/BlueWest.Data/Finance/Currency/CurrencyUpdate.cs +++ b/BlueWest.Data/Currency/CurrencyUpdate.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using MapTo; namespace BlueWest.Data @@ -8,7 +9,7 @@ namespace BlueWest.Data public partial class CurrencyUpdate { // ISO 4217 Code - public string Code { get; set; } + [MaxLength(3)] public string Code { get; set; } } diff --git a/BlueWest.Data/Finance/Currency/TestData.cs b/BlueWest.Data/Currency/TestData.cs similarity index 100% rename from BlueWest.Data/Finance/Currency/TestData.cs rename to BlueWest.Data/Currency/TestData.cs diff --git a/BlueWest.Data/Finance/Transaction/FinanceTransaction.cs b/BlueWest.Data/Transaction/FinanceTransaction.cs similarity index 100% rename from BlueWest.Data/Finance/Transaction/FinanceTransaction.cs rename to BlueWest.Data/Transaction/FinanceTransaction.cs diff --git a/BlueWest.Data/Finance/Transaction/FinanceTransactionInsertDto.cs b/BlueWest.Data/Transaction/FinanceTransactionInsertDto.cs similarity index 100% rename from BlueWest.Data/Finance/Transaction/FinanceTransactionInsertDto.cs rename to BlueWest.Data/Transaction/FinanceTransactionInsertDto.cs diff --git a/BlueWest.Data/Finance/Transaction/FinanceTransactionReadDto.cs b/BlueWest.Data/Transaction/FinanceTransactionReadDto.cs similarity index 100% rename from BlueWest.Data/Finance/Transaction/FinanceTransactionReadDto.cs rename to BlueWest.Data/Transaction/FinanceTransactionReadDto.cs diff --git a/BlueWest.Data/Finance/Transaction/FinanceTransactionType.cs b/BlueWest.Data/Transaction/FinanceTransactionType.cs similarity index 100% rename from BlueWest.Data/Finance/Transaction/FinanceTransactionType.cs rename to BlueWest.Data/Transaction/FinanceTransactionType.cs diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs index 7049a8e..3c89df6 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs @@ -30,18 +30,22 @@ namespace MapTo.Extensions internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - return builder - .WriteLine() - .WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}") - .WriteComment($" HasMappedBaseClass {model.HasMappedBaseClass.ToString()}") - .WriteComment($" Namespace {model.Namespace}") - .WriteComment($" Options {model.Options.ToString()}") - .WriteComment($" Type {model.Type}") - .WriteComment($" TypeIdentifierName {model.TypeIdentifierName}") - .WriteComment($" SourceNamespace {targetSourceType.SourceNamespace}") - .WriteComment($" SourceTypeFullName {targetSourceType.SourceTypeFullName}") - .WriteComment($" SourceTypeIdentifierName {targetSourceType.SourceTypeIdentifierName}"); + foreach (var targetSourceType in model.MappedSourceTypes) + { + builder + .WriteLine() + .WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}") + .WriteComment($" HasMappedBaseClass {model.HasMappedBaseClass.ToString()}") + .WriteComment($" Namespace {model.Namespace}") + .WriteComment($" Options {model.Options.ToString()}") + .WriteComment($" Type {model.Type}") + .WriteComment($" TypeIdentifierName {model.TypeIdentifierName}") + .WriteComment($" SourceNamespace {targetSourceType.SourceNamespace}") + .WriteComment($" SourceTypeFullName {targetSourceType.SourceTypeFullName}") + .WriteComment($" SourceTypeIdentifierName {targetSourceType.SourceTypeIdentifierName}"); + } + + return builder; } diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs index 61f6103..0b58acd 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs @@ -15,7 +15,6 @@ namespace MapTo.Extensions { const bool writeDebugInfo = true; - var targetSourceType = model.MappedSourceTypes[0]; using var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) @@ -26,24 +25,31 @@ namespace MapTo.Extensions // Namespace declaration .WriteLine($"namespace {model.Namespace}") .WriteOpeningBracket(); + + + + foreach (var targetSourceType in model.MappedSourceTypes) + { + if (writeDebugInfo) + builder + .WriteModelInfo(model) + .WriteLine() + .WriteComment("Type properties") + .WriteComment() + .WriteMappedProperties(targetSourceType.TypeProperties) + .WriteLine() + .WriteComment("Source properties") + .WriteLine() + .WriteComment("Type fields") + .WriteComment() + .WriteMappedProperties(targetSourceType.TypeFields) + .WriteLine() + .WriteComment("Source fields") + .WriteMappedProperties(targetSourceType.SourceFields) + .WriteLine(); + + } - if (writeDebugInfo) - builder - .WriteModelInfo(model) - .WriteLine() - .WriteComment("Type properties") - .WriteComment() - .WriteMappedProperties(targetSourceType.TypeProperties) - .WriteLine() - .WriteComment("Source properties") - .WriteLine() - .WriteComment("Type fields") - .WriteComment() - .WriteMappedProperties(targetSourceType.TypeFields) - .WriteLine() - .WriteComment("Source fields") - .WriteMappedProperties(targetSourceType.SourceFields) - .WriteLine(); builder // Class declaration @@ -52,10 +58,14 @@ namespace MapTo.Extensions .WriteLine() // Class body .GeneratePublicConstructor(model); - + foreach (var targetSourceType in model.MappedSourceTypes) + { + if (model.IsTypeUpdatable && targetSourceType.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); + if (model.IsTypeUpdatable && targetSourceType.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); + } + if (model.IsJsonExtension) builder.WriteToJsonMethod(model); - if (model.IsTypeUpdatable && targetSourceType.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); - if (model.IsTypeUpdatable && targetSourceType.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); + builder .WriteLine() @@ -70,46 +80,47 @@ namespace MapTo.Extensions private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); const string mappingContextParameterName = "context"; - var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty; - - var stringBuilder = new StringBuilder(); - - var otherProperties = new List(); - - foreach (var property in targetSourceType.TypeProperties) + foreach (var targetSourceType in model.MappedSourceTypes) { - if (!targetSourceType.SourceProperties.IsMappedProperty(property)) + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty; + var stringBuilder = new StringBuilder(); + var otherProperties = new List(); + + foreach (var property in targetSourceType.TypeProperties) { - stringBuilder.Append(", "); - stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); - otherProperties.Add(property); + if (!targetSourceType.SourceProperties.IsMappedProperty(property)) + { + stringBuilder.Append(", "); + stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); + otherProperties.Add(property); + } + } - } - - foreach (var property in targetSourceType.TypeFields) - { - if (!targetSourceType.SourceFields.IsMappedProperty(property)) + foreach (var property in targetSourceType.TypeFields) { - stringBuilder.Append(", "); - stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); - otherProperties.Add(property); + if (!targetSourceType.SourceFields.IsMappedProperty(property)) + { + stringBuilder.Append(", "); + stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); + otherProperties.Add(property); + } } + + var readOnlyPropertiesArguments = stringBuilder.ToString(); + + builder + .WriteLine($"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") + .WriteOpeningBracket() + .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); + + builder.WriteClosingBracket(); } - - var readOnlyPropertiesArguments = stringBuilder.ToString(); - - builder - .WriteLine($"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") - .WriteOpeningBracket() - .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); - // End constructor declaration - return builder.WriteClosingBracket(); + return builder; } private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray properties, MappedMember property) @@ -131,29 +142,33 @@ namespace MapTo.Extensions .WriteLine("var stringBuilder = new System.Text.StringBuilder();") .WriteLine(GetStringBuilderAppendNoInterpolation("{")); - var targetSourceType = model.MappedSourceTypes[0]; - foreach (var property in targetSourceType.TypeProperties) + foreach (var targetSourceType in model.MappedSourceTypes) { - if (!property.isEnumerable) - HandlePropertyEnumerable(builder, property); - else + foreach (var property in targetSourceType.TypeProperties) { - builder = WriteJsonField(builder, property); + if (!property.isEnumerable) + HandlePropertyEnumerable(builder, property); + else + { + builder = WriteJsonField(builder, property); + } } - } - foreach (var property in targetSourceType.TypeFields) - { - if (!property.isEnumerable) - HandleFieldEnumerable(builder, property); - else + foreach (var property in targetSourceType.TypeFields) { - builder.WriteLine(GetStringBuilderAppend($"\\\"{property.Name.ToCamelCase()}\\\" : [{GetJsonArrayValue(property, ref builder)}],")); + if (!property.isEnumerable) + HandleFieldEnumerable(builder, property); + else + { + builder.WriteLine(GetStringBuilderAppend($"\\\"{property.Name.ToCamelCase()}\\\" : [{GetJsonArrayValue(property, ref builder)}],")); + } } + + builder.WriteLine(GetStringBuilderAppendNoInterpolation("}")); + builder.WriteLine("return stringBuilder.ToString();"); + builder.WriteClosingBracket(); } + - builder.WriteLine(GetStringBuilderAppendNoInterpolation("}")); - builder.WriteLine("return stringBuilder.ToString();"); - builder.WriteClosingBracket(); return builder; } @@ -231,33 +246,48 @@ namespace MapTo.Extensions private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray? otherProperties, string? sourceClassParameterName, string mappingContextParameterName, bool fromUpdate) { - var targetSourceType = model.MappedSourceTypes[0]; - foreach (var property in targetSourceType.SourceProperties) + List _addedMembers = new List(); + + foreach (var targetSourceType in model.MappedSourceTypes) { - if (property.isReadOnly && fromUpdate) continue; + foreach (var property in targetSourceType.SourceProperties) + { + if (property.isReadOnly && fromUpdate) continue; + if(_addedMembers.Contains(property)) continue; + - builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};"); + builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};"); + _addedMembers.Add(property); + } + + foreach (var property in targetSourceType.SourceFields) + { + if (property.isReadOnly && fromUpdate) continue; + if(_addedMembers.Contains(property)) continue; + + builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};"); + _addedMembers.Add(property); + + } + + if (otherProperties == null) return builder; + + foreach (var property in otherProperties) + { + if(_addedMembers.Contains(property)) continue; + + builder.WriteLine(property.MappedSourcePropertyTypeName is null + ? $"{property.Name} = {property.SourcePropertyName.ToCamelCase()};" + : ""); + _addedMembers.Add(property); + + + } } - foreach (var property in targetSourceType.SourceFields) - { - if (property.isReadOnly && fromUpdate) continue; - - builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};"); - - } - - if (otherProperties == null) return builder; - - foreach (var property in otherProperties) - { - builder.WriteLine(property.MappedSourcePropertyTypeName is null - ? $"{property.Name} = {property.SourcePropertyName.ToCamelCase()};" - : ""); - - } + return builder; @@ -266,15 +296,19 @@ namespace MapTo.Extensions private static SourceBuilder GenerateUpdateMethod(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); - builder - .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) - .WriteLine($"public void Update({targetSourceType.SourceType} {sourceClassParameterName})") - .WriteOpeningBracket() - .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true) - .WriteClosingBracket(); + foreach (var targetSourceType in model.MappedSourceTypes) + { + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + + builder + .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) + .WriteLine($"public void Update({targetSourceType.SourceType} {sourceClassParameterName})") + .WriteOpeningBracket() + .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true) + .WriteClosingBracket(); + } + return builder; } @@ -286,28 +320,37 @@ namespace MapTo.Extensions return builder; } - var targetSourceType = model.MappedSourceTypes[0]; + foreach (var targetSourceType in model.MappedSourceTypes) + { + builder + .WriteLine("/// ") + .WriteLine($"/// Updates and sets its participating properties") + .WriteLine($"/// using the property values from .") + .WriteLine("/// ") + .WriteLine($"/// The instance of to use as source."); - return builder - .WriteLine("/// ") - .WriteLine($"/// Updates and sets its participating properties") - .WriteLine($"/// using the property values from .") - .WriteLine("/// ") - .WriteLine($"/// The instance of to use as source."); + } + + return builder; } private static SourceBuilder GenerateEnumerableJsonSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + foreach (var targetSourceType in model.MappedSourceTypes) + { + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); - return builder - .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") - .WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static string ToJson(this IEnumerable<{targetSourceType.SourceType}{model.Options.NullableReferenceSyntax}> {sourceClassParameterName}List)") - .WriteOpeningBracket() - .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") - .WriteClosingBracket(); + builder + .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") + .WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static string ToJson(this IEnumerable<{targetSourceType.SourceType}{model.Options.NullableReferenceSyntax}> {sourceClassParameterName}List)") + .WriteOpeningBracket() + .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") + .WriteClosingBracket(); + } + + + return builder; } } } diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs index a55f51c..8699d19 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs @@ -22,15 +22,18 @@ namespace MapTo.Sources .WriteLine($"partial record {model.TypeIdentifierName}") .WriteOpeningBracket(); - var targetSourceType = model.MappedSourceTypes[0]; + foreach (var targetSourceType in model.MappedSourceTypes) + { + if (targetSourceType.GenerateSecondaryConstructor) + { + builder + .GenerateSecondaryConstructor(model) + .WriteLine(); + } + } // Class body - if (targetSourceType.GenerateSecondaryConstructor) - { - builder - .GenerateSecondaryConstructor(model) - .WriteLine(); - } + builder .GeneratePrivateConstructor(model) @@ -55,105 +58,118 @@ namespace MapTo.Sources private static SourceBuilder GenerateSecondaryConstructor(this SourceBuilder builder, MappingModel model) { // grab first data from array - var targetSourceType = model.MappedSourceTypes[0]; - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); - if (model.Options.GenerateXmlDocument) + foreach (var targetSourceType in model.MappedSourceTypes) { - builder - .WriteLine("/// ") - .WriteLine($"/// Initializes a new instance of the class") - .WriteLine($"/// using the property values from the specified .") - .WriteLine("/// ") - .WriteLine($"/// {sourceClassParameterName} is null"); + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + if (model.Options.GenerateXmlDocument) + { + builder + .WriteLine("/// ") + .WriteLine($"/// Initializes a new instance of the class") + .WriteLine($"/// using the property values from the specified .") + .WriteLine("/// ") + .WriteLine($"/// {sourceClassParameterName} is null"); + } + builder .WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName})") + .WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}"); } - return builder - .WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName})") - .WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}"); + + + return builder; + } private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); const string mappingContextParameterName = "context"; - builder - .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {targetSourceType.SourceType} {sourceClassParameterName})") - .Indent() - .Write(": this("). - - WriteProperties(model, sourceClassParameterName, mappingContextParameterName) - - .WriteLine(")") - .Unindent() - .WriteOpeningBracket() - .WriteLine($"if ({mappingContextParameterName} == null) throw new ArgumentNullException(nameof({mappingContextParameterName}));") - .WriteLine($"if ({sourceClassParameterName} == null) throw new ArgumentNullException(nameof({sourceClassParameterName}));") - .WriteLine() - .WriteLine($"{mappingContextParameterName}.{MappingContextSource.RegisterMethodName}({sourceClassParameterName}, this);"); - + foreach (var targetSourceType in model.MappedSourceTypes) + { + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + builder + .WriteLine( + $"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {targetSourceType.SourceType} {sourceClassParameterName})") + .Indent() + .Write(": this(").WriteProperties(model, sourceClassParameterName, mappingContextParameterName) + .WriteLine(")") + .Unindent() + .WriteOpeningBracket() + .WriteLine($"if ({mappingContextParameterName} == null) throw new ArgumentNullException(nameof({mappingContextParameterName}));") + .WriteLine($"if ({sourceClassParameterName} == null) throw new ArgumentNullException(nameof({sourceClassParameterName}));") + .WriteLine() + .WriteLine($"{mappingContextParameterName}.{MappingContextSource.RegisterMethodName}({sourceClassParameterName}, this);") + .WriteClosingBracket(); + } // End constructor declaration - return builder.WriteClosingBracket(); + return builder; } private static SourceBuilder WriteProperties(this SourceBuilder builder, MappingModel model, string sourceClassParameterName, string mappingContextParameterName) { - var targetSourceType = model.MappedSourceTypes[0]; - for (var i = 0; i < targetSourceType.SourceProperties.Length; i++) + foreach (var targetSourceType in model.MappedSourceTypes) { - var property = targetSourceType.SourceProperties[i]; - if (property.TypeConverter is null) + for (var i = 0; i < targetSourceType.SourceProperties.Length; i++) { - if (property.IsEnumerable) + var property = targetSourceType.SourceProperties[i]; + if (property.TypeConverter is null) { - builder.Write( - $"{property.Name}: {sourceClassParameterName}.{property.SourcePropertyName}.Select({mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.EnumerableTypeArgument}>).ToList()"); + if (property.IsEnumerable) + { + builder.Write( + $"{property.Name}: {sourceClassParameterName}.{property.SourcePropertyName}.Select({mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.EnumerableTypeArgument}>).ToList()"); + } + else + { + builder.Write(property.MappedSourcePropertyTypeName is null + ? $"{property.Name}: {sourceClassParameterName}.{property.SourcePropertyName}" + : $"{property.Name}: {mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.Type}>({sourceClassParameterName}.{property.SourcePropertyName})"); + } } else { - builder.Write(property.MappedSourcePropertyTypeName is null - ? $"{property.Name}: {sourceClassParameterName}.{property.SourcePropertyName}" - : $"{property.Name}: {mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.Type}>({sourceClassParameterName}.{property.SourcePropertyName})"); + var parameters = property.TypeConverterParameters.IsEmpty + ? "null" + : $"new object[] {{ {string.Join(", ", property.TypeConverterParameters)} }}"; + + builder.Write( + $"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})"); + } + + if (i < targetSourceType.SourceProperties.Length - 1) + { + builder.Write(", "); } } - else - { - var parameters = property.TypeConverterParameters.IsEmpty - ? "null" - : $"new object[] {{ {string.Join(", ", property.TypeConverterParameters)} }}"; - - builder.Write( - $"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})"); - } - - if (i < targetSourceType.SourceProperties.Length - 1) - { - builder.Write(", "); - } } + + return builder; } private static SourceBuilder GenerateFactoryMethod(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + foreach (var targetSourceType in model.MappedSourceTypes) + { + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); - return builder - .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) - .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") - .WriteLine( - $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} From({targetSourceType.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") - .WriteOpeningBracket() - .WriteLine( - $"return {sourceClassParameterName} == null ? null : {MappingContextSource.ClassName}.{MappingContextSource.FactoryMethodName}<{targetSourceType.SourceType}, {model.TypeIdentifierName}>({sourceClassParameterName});") - .WriteClosingBracket(); + builder + .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) + .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") + .WriteLine( + $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} From({targetSourceType.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") + .WriteOpeningBracket() + .WriteLine( + $"return {sourceClassParameterName} == null ? null : {MappingContextSource.ClassName}.{MappingContextSource.FactoryMethodName}<{targetSourceType.SourceType}, {model.TypeIdentifierName}>({sourceClassParameterName});") + .WriteClosingBracket(); + } + + + return builder; } private static SourceBuilder GenerateConvertorMethodsXmlDocs(this SourceBuilder builder, MappingModel model, string sourceClassParameterName) @@ -162,44 +178,58 @@ namespace MapTo.Sources { return builder; } - var targetSourceType = model.MappedSourceTypes[0]; - return builder - .WriteLine("/// ") - .WriteLine($"/// Creates a new instance of and sets its participating properties") - .WriteLine($"/// using the property values from .") - .WriteLine("/// ") - .WriteLine($"/// The instance of to use as source.") - .WriteLine( - $"/// A new instance of -or- null if is null."); + foreach (var targetSourceType in model.MappedSourceTypes) + { + builder + .WriteLine("/// ") + .WriteLine($"/// Creates a new instance of and sets its participating properties") + .WriteLine($"/// using the property values from .") + .WriteLine("/// ") + .WriteLine($"/// The instance of to use as source.") + .WriteLine( + $"/// A new instance of -or- null if is null."); + } + + return builder; + } private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; + foreach (var targetSourceType in model.MappedSourceTypes) + { + builder + .WriteLine( + $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {targetSourceType.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions") + .WriteOpeningBracket() + .GenerateSourceTypeExtensionMethod(model) + .WriteClosingBracket(); + } - return builder - .WriteLine( - $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {targetSourceType.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions") - .WriteOpeningBracket() - .GenerateSourceTypeExtensionMethod(model) - .WriteClosingBracket(); + return builder; } private static SourceBuilder GenerateSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) { - var targetSourceType = model.MappedSourceTypes[0]; - var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); + foreach (var targetSourceType in model.MappedSourceTypes) + { + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); - return builder - .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) - .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") - .WriteLine( - $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} To{model.TypeIdentifierName}(this {targetSourceType.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") - .WriteOpeningBracket() - .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") - .WriteClosingBracket(); + builder + .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) + .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") + .WriteLine( + $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} To{model.TypeIdentifierName}(this {targetSourceType.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") + .WriteOpeningBracket() + .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") + .WriteClosingBracket(); + + } + + + return builder; } } } \ No newline at end of file