From 3a2d3a1b41629c8d0fc88f559469635517c80325 Mon Sep 17 00:00:00 2001 From: CodeLiturgy Date: Thu, 18 Aug 2022 16:01:39 +0100 Subject: [PATCH] Add MappedSourceType to the list --- BlueWest.Data/Finance/Currency/Country.cs | 2 +- .../Extensions/CommonExtensions.cs | 7 ++- .../BlueWest.MapTo/Extensions/CommonSource.cs | 50 ++++++++++------- .../src/BlueWest.MapTo/MappingContext.cs | 55 ++++++++++--------- .../src/BlueWest.MapTo/Models.cs | 28 ++++++---- .../BlueWest.MapTo/Sources/MapRecordSource.cs | 44 ++++++++++----- 6 files changed, 111 insertions(+), 75 deletions(-) diff --git a/BlueWest.Data/Finance/Currency/Country.cs b/BlueWest.Data/Finance/Currency/Country.cs index bbc44a3..1530c54 100644 --- a/BlueWest.Data/Finance/Currency/Country.cs +++ b/BlueWest.Data/Finance/Currency/Country.cs @@ -5,7 +5,7 @@ using MapTo; namespace BlueWest.Data { - [MapFrom(typeof(CountryUpdate))] + [MapFrom(new [] {typeof(CountryUpdate), typeof(CountryCreate)})] public partial class Country { // ISO 3166-1 numeric code diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs index edc2e23..7049a8e 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonExtensions.cs @@ -30,6 +30,7 @@ namespace MapTo.Extensions internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model) { + var targetSourceType = model.MappedSourceTypes[0]; return builder .WriteLine() .WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}") @@ -38,9 +39,9 @@ namespace MapTo.Extensions .WriteComment($" Options {model.Options.ToString()}") .WriteComment($" Type {model.Type}") .WriteComment($" TypeIdentifierName {model.TypeIdentifierName}") - .WriteComment($" SourceNamespace {model.SourceNamespace}") - .WriteComment($" SourceTypeFullName {model.SourceTypeFullName}") - .WriteComment($" SourceTypeIdentifierName {model.SourceTypeIdentifierName}"); + .WriteComment($" SourceNamespace {targetSourceType.SourceNamespace}") + .WriteComment($" SourceTypeFullName {targetSourceType.SourceTypeFullName}") + .WriteComment($" SourceTypeIdentifierName {targetSourceType.SourceTypeIdentifierName}"); } diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs index 07f0413..61f6103 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Extensions/CommonSource.cs @@ -15,6 +15,8 @@ namespace MapTo.Extensions { const bool writeDebugInfo = true; + var targetSourceType = model.MappedSourceTypes[0]; + using var builder = new SourceBuilder() .WriteLine(GeneratedFilesHeader) .WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes) @@ -31,16 +33,16 @@ namespace MapTo.Extensions .WriteLine() .WriteComment("Type properties") .WriteComment() - .WriteMappedProperties(model.TypeProperties) + .WriteMappedProperties(targetSourceType.TypeProperties) .WriteLine() .WriteComment("Source properties") .WriteLine() .WriteComment("Type fields") .WriteComment() - .WriteMappedProperties(model.TypeFields) + .WriteMappedProperties(targetSourceType.TypeFields) .WriteLine() .WriteComment("Source fields") - .WriteMappedProperties(model.SourceFields) + .WriteMappedProperties(targetSourceType.SourceFields) .WriteLine(); builder @@ -52,8 +54,8 @@ namespace MapTo.Extensions .GeneratePublicConstructor(model); if (model.IsJsonExtension) builder.WriteToJsonMethod(model); - if (model.IsTypeUpdatable && model.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); - if (model.IsTypeUpdatable && model.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(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() @@ -68,7 +70,8 @@ namespace MapTo.Extensions private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + var targetSourceType = model.MappedSourceTypes[0]; + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); const string mappingContextParameterName = "context"; var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty; @@ -77,9 +80,9 @@ namespace MapTo.Extensions var otherProperties = new List(); - foreach (var property in model.TypeProperties) + foreach (var property in targetSourceType.TypeProperties) { - if (!model.SourceProperties.IsMappedProperty(property)) + if (!targetSourceType.SourceProperties.IsMappedProperty(property)) { stringBuilder.Append(", "); stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); @@ -87,9 +90,9 @@ namespace MapTo.Extensions } } - foreach (var property in model.TypeFields) + foreach (var property in targetSourceType.TypeFields) { - if (!model.SourceFields.IsMappedProperty(property)) + if (!targetSourceType.SourceFields.IsMappedProperty(property)) { stringBuilder.Append(", "); stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); @@ -101,7 +104,7 @@ namespace MapTo.Extensions var readOnlyPropertiesArguments = stringBuilder.ToString(); builder - .WriteLine($"public {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") + .WriteLine($"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") .WriteOpeningBracket() .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); @@ -128,7 +131,8 @@ namespace MapTo.Extensions .WriteLine("var stringBuilder = new System.Text.StringBuilder();") .WriteLine(GetStringBuilderAppendNoInterpolation("{")); - foreach (var property in model.TypeProperties) + var targetSourceType = model.MappedSourceTypes[0]; + foreach (var property in targetSourceType.TypeProperties) { if (!property.isEnumerable) HandlePropertyEnumerable(builder, property); @@ -137,7 +141,7 @@ namespace MapTo.Extensions builder = WriteJsonField(builder, property); } } - foreach (var property in model.TypeFields) + foreach (var property in targetSourceType.TypeFields) { if (!property.isEnumerable) HandleFieldEnumerable(builder, property); @@ -227,8 +231,9 @@ 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 model.SourceProperties) + foreach (var property in targetSourceType.SourceProperties) { if (property.isReadOnly && fromUpdate) continue; @@ -236,7 +241,7 @@ namespace MapTo.Extensions } - foreach (var property in model.SourceFields) + foreach (var property in targetSourceType.SourceFields) { if (property.isReadOnly && fromUpdate) continue; @@ -261,11 +266,12 @@ namespace MapTo.Extensions private static SourceBuilder GenerateUpdateMethod(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + var targetSourceType = model.MappedSourceTypes[0]; + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); builder .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) - .WriteLine($"public void Update({model.SourceType} {sourceClassParameterName})") + .WriteLine($"public void Update({targetSourceType.SourceType} {sourceClassParameterName})") .WriteOpeningBracket() .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true) .WriteClosingBracket(); @@ -280,21 +286,25 @@ namespace MapTo.Extensions return builder; } + var targetSourceType = model.MappedSourceTypes[0]; + 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."); + .WriteLine($"/// The instance of to use as source."); } private static SourceBuilder GenerateEnumerableJsonSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + var targetSourceType = model.MappedSourceTypes[0]; + + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); return builder .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") - .WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static string ToJson(this IEnumerable<{model.SourceType}{model.Options.NullableReferenceSyntax}> {sourceClassParameterName}List)") + .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(); diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/MappingContext.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/MappingContext.cs index 2f762f4..e7b7fdd 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/MappingContext.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/MappingContext.cs @@ -503,52 +503,57 @@ namespace MapTo AddDiagnostic(DiagnosticsFactory.MapFromAttributeNotFoundError(TypeSyntax.GetLocation())); return null; } - - var sourceTypeSymbol = sourceTypeSymbols[0]; - // Pick first one to avoid errors. TODO: Make possible to use different source types - - _ignoredNamespaces.Add(sourceTypeSymbol.ContainingNamespace.ToDisplayParts().First()); - + var typeIdentifierName = TypeSyntax.GetIdentifierName(); - var sourceTypeIdentifierName = sourceTypeSymbol.Name; var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel); var isTypeUpdatable = false; //IsTypeUpdatable(); var hasJsonExtension = false; // HasJsonExtension(); - var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol); - var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); - var mappedFields = GetSourceMappedFields(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); + List mappedSourceTypes = new List(); + + foreach (var sourceTypeSymbol in sourceTypeSymbols) + { + _ignoredNamespaces.Add(sourceTypeSymbol.ContainingNamespace.ToDisplayParts().First()); + var sourceTypeIdentifierName = sourceTypeSymbol.Name; + var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol); + var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); + var mappedFields = GetSourceMappedFields(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); + AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq"); + var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass); + var allFields = GetTypeMappedFields(sourceTypeSymbol, typeSymbol, isTypeInheritFromMappedBaseClass); + + mappedSourceTypes.Add(new MappedSourceType( + sourceTypeSymbol.ContainingNamespace.ToDisplayString(), + sourceTypeIdentifierName, + sourceTypeSymbol.ToDisplayString(), + mappedProperties, mappedFields, allProperties, allFields, shouldGenerateSecondaryConstructor)); + } + + //var sourceTypeSymbol = sourceTypeSymbols[0]; + + // Pick first one to avoid errors. TODO: Make possible to use different source types + + + /*if (!mappedProperties.Any()) { AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyFoundError(TypeSyntax.GetLocation(), typeSymbol, sourceTypeSymbol)); return null; }*/ - - AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq"); - - var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass); - var allFields = GetTypeMappedFields(sourceTypeSymbol, typeSymbol, isTypeInheritFromMappedBaseClass); - + return new MappingModel( SourceGenerationOptions, TypeSyntax.GetNamespace(), TypeSyntax.Modifiers, TypeSyntax.Keyword.Text, typeIdentifierName, - sourceTypeSymbol.ContainingNamespace.ToDisplayString(), - sourceTypeIdentifierName, - sourceTypeSymbol.ToDisplayString(), isTypeUpdatable, hasJsonExtension, - mappedProperties, - allProperties, - mappedFields, - allFields, + mappedSourceTypes.ToImmutableArray(), isTypeInheritFromMappedBaseClass, - Usings, - shouldGenerateSecondaryConstructor); + Usings); } diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Models.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Models.cs index e10dcbf..8c8869b 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Models.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Models.cs @@ -39,29 +39,35 @@ namespace MapTo public bool IsEnumerable => EnumerableTypeArgument is not null; } - internal record MappingModel ( - SourceGenerationOptions Options, - string? Namespace, - SyntaxTokenList Modifiers, - string Type, - string TypeIdentifierName, + internal record MappedSourceType + ( string SourceNamespace, string SourceTypeIdentifierName, string SourceTypeFullName, - bool IsTypeUpdatable, - bool IsJsonExtension, ImmutableArray SourceProperties, - ImmutableArray TypeProperties, ImmutableArray SourceFields, + ImmutableArray TypeProperties, ImmutableArray TypeFields, - bool HasMappedBaseClass, - ImmutableArray Usings, bool GenerateSecondaryConstructor ) { public string SourceType => SourceTypeFullName; } + + internal record MappingModel( + SourceGenerationOptions Options, + string? Namespace, + SyntaxTokenList Modifiers, + string Type, + string TypeIdentifierName, + bool IsTypeUpdatable, + bool IsJsonExtension, + ImmutableArray MappedSourceTypes, + bool HasMappedBaseClass, + ImmutableArray Usings + ); + internal record SourceGenerationOptions( AccessModifier ConstructorAccessModifier, AccessModifier GeneratedMethodsAccessModifier, diff --git a/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs b/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs index baa48b5..a55f51c 100644 --- a/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs +++ b/include/BlueWest.MapTo/src/BlueWest.MapTo/Sources/MapRecordSource.cs @@ -22,8 +22,10 @@ namespace MapTo.Sources .WriteLine($"partial record {model.TypeIdentifierName}") .WriteOpeningBracket(); + var targetSourceType = model.MappedSourceTypes[0]; + // Class body - if (model.GenerateSecondaryConstructor) + if (targetSourceType.GenerateSecondaryConstructor) { builder .GenerateSecondaryConstructor(model) @@ -52,7 +54,9 @@ namespace MapTo.Sources private static SourceBuilder GenerateSecondaryConstructor(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + // grab first data from array + var targetSourceType = model.MappedSourceTypes[0]; + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); if (model.Options.GenerateXmlDocument) { @@ -65,17 +69,19 @@ namespace MapTo.Sources } return builder - .WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName})") + .WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName})") .WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}"); } private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + var targetSourceType = model.MappedSourceTypes[0]; + + var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase(); const string mappingContextParameterName = "context"; builder - .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {model.SourceType} {sourceClassParameterName})") + .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {targetSourceType.SourceType} {sourceClassParameterName})") .Indent() .Write(": this("). @@ -96,9 +102,11 @@ namespace MapTo.Sources private static SourceBuilder WriteProperties(this SourceBuilder builder, MappingModel model, string sourceClassParameterName, string mappingContextParameterName) { - for (var i = 0; i < model.SourceProperties.Length; i++) + var targetSourceType = model.MappedSourceTypes[0]; + + for (var i = 0; i < targetSourceType.SourceProperties.Length; i++) { - var property = model.SourceProperties[i]; + var property = targetSourceType.SourceProperties[i]; if (property.TypeConverter is null) { if (property.IsEnumerable) @@ -123,7 +131,7 @@ namespace MapTo.Sources $"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})"); } - if (i < model.SourceProperties.Length - 1) + if (i < targetSourceType.SourceProperties.Length - 1) { builder.Write(", "); } @@ -134,16 +142,17 @@ namespace MapTo.Sources private static SourceBuilder GenerateFactoryMethod(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + var targetSourceType = model.MappedSourceTypes[0]; + 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({model.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") + $"{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}<{model.SourceType}, {model.TypeIdentifierName}>({sourceClassParameterName});") + $"return {sourceClassParameterName} == null ? null : {MappingContextSource.ClassName}.{MappingContextSource.FactoryMethodName}<{targetSourceType.SourceType}, {model.TypeIdentifierName}>({sourceClassParameterName});") .WriteClosingBracket(); } @@ -153,22 +162,25 @@ 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($"/// The instance of to use as source.") .WriteLine( $"/// A new instance of -or- null if is null."); } private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model) { + var targetSourceType = model.MappedSourceTypes[0]; + return builder .WriteLine( - $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {model.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions") + $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {targetSourceType.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions") .WriteOpeningBracket() .GenerateSourceTypeExtensionMethod(model) .WriteClosingBracket(); @@ -176,13 +188,15 @@ namespace MapTo.Sources private static SourceBuilder GenerateSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) { - var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); + var targetSourceType = model.MappedSourceTypes[0]; + + 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 {model.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") + $"{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();