Add MappedSourceType to the list

This commit is contained in:
CodeLiturgy 2022-08-18 16:01:39 +01:00
parent 2cd2a3868c
commit 3a2d3a1b41
6 changed files with 111 additions and 75 deletions

View File

@ -5,7 +5,7 @@ using MapTo;
namespace BlueWest.Data namespace BlueWest.Data
{ {
[MapFrom(typeof(CountryUpdate))] [MapFrom(new [] {typeof(CountryUpdate), typeof(CountryCreate)})]
public partial class Country public partial class Country
{ {
// ISO 3166-1 numeric code // ISO 3166-1 numeric code

View File

@ -30,6 +30,7 @@ namespace MapTo.Extensions
internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model) internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model)
{ {
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine() .WriteLine()
.WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}") .WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}")
@ -38,9 +39,9 @@ namespace MapTo.Extensions
.WriteComment($" Options {model.Options.ToString()}") .WriteComment($" Options {model.Options.ToString()}")
.WriteComment($" Type {model.Type}") .WriteComment($" Type {model.Type}")
.WriteComment($" TypeIdentifierName {model.TypeIdentifierName}") .WriteComment($" TypeIdentifierName {model.TypeIdentifierName}")
.WriteComment($" SourceNamespace {model.SourceNamespace}") .WriteComment($" SourceNamespace {targetSourceType.SourceNamespace}")
.WriteComment($" SourceTypeFullName {model.SourceTypeFullName}") .WriteComment($" SourceTypeFullName {targetSourceType.SourceTypeFullName}")
.WriteComment($" SourceTypeIdentifierName {model.SourceTypeIdentifierName}"); .WriteComment($" SourceTypeIdentifierName {targetSourceType.SourceTypeIdentifierName}");
} }

View File

@ -15,6 +15,8 @@ namespace MapTo.Extensions
{ {
const bool writeDebugInfo = true; const bool writeDebugInfo = true;
var targetSourceType = model.MappedSourceTypes[0];
using var builder = new SourceBuilder() using var builder = new SourceBuilder()
.WriteLine(GeneratedFilesHeader) .WriteLine(GeneratedFilesHeader)
.WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes) .WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes)
@ -31,16 +33,16 @@ namespace MapTo.Extensions
.WriteLine() .WriteLine()
.WriteComment("Type properties") .WriteComment("Type properties")
.WriteComment() .WriteComment()
.WriteMappedProperties(model.TypeProperties) .WriteMappedProperties(targetSourceType.TypeProperties)
.WriteLine() .WriteLine()
.WriteComment("Source properties") .WriteComment("Source properties")
.WriteLine() .WriteLine()
.WriteComment("Type fields") .WriteComment("Type fields")
.WriteComment() .WriteComment()
.WriteMappedProperties(model.TypeFields) .WriteMappedProperties(targetSourceType.TypeFields)
.WriteLine() .WriteLine()
.WriteComment("Source fields") .WriteComment("Source fields")
.WriteMappedProperties(model.SourceFields) .WriteMappedProperties(targetSourceType.SourceFields)
.WriteLine(); .WriteLine();
builder builder
@ -52,8 +54,8 @@ namespace MapTo.Extensions
.GeneratePublicConstructor(model); .GeneratePublicConstructor(model);
if (model.IsJsonExtension) builder.WriteToJsonMethod(model); if (model.IsJsonExtension) builder.WriteToJsonMethod(model);
if (model.IsTypeUpdatable && model.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); if (model.IsTypeUpdatable && targetSourceType.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model);
if (model.IsTypeUpdatable && model.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); if (model.IsTypeUpdatable && targetSourceType.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model);
builder builder
.WriteLine() .WriteLine()
@ -68,7 +70,8 @@ namespace MapTo.Extensions
private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model) 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"; const string mappingContextParameterName = "context";
var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty; var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty;
@ -77,9 +80,9 @@ namespace MapTo.Extensions
var otherProperties = new List<MappedMember>(); var otherProperties = new List<MappedMember>();
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(", ");
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); 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(", ");
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
@ -101,7 +104,7 @@ namespace MapTo.Extensions
var readOnlyPropertiesArguments = stringBuilder.ToString(); var readOnlyPropertiesArguments = stringBuilder.ToString();
builder builder
.WriteLine($"public {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") .WriteLine($"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false);
@ -128,7 +131,8 @@ namespace MapTo.Extensions
.WriteLine("var stringBuilder = new System.Text.StringBuilder();") .WriteLine("var stringBuilder = new System.Text.StringBuilder();")
.WriteLine(GetStringBuilderAppendNoInterpolation("{")); .WriteLine(GetStringBuilderAppendNoInterpolation("{"));
foreach (var property in model.TypeProperties) var targetSourceType = model.MappedSourceTypes[0];
foreach (var property in targetSourceType.TypeProperties)
{ {
if (!property.isEnumerable) if (!property.isEnumerable)
HandlePropertyEnumerable(builder, property); HandlePropertyEnumerable(builder, property);
@ -137,7 +141,7 @@ namespace MapTo.Extensions
builder = WriteJsonField(builder, property); builder = WriteJsonField(builder, property);
} }
} }
foreach (var property in model.TypeFields) foreach (var property in targetSourceType.TypeFields)
{ {
if (!property.isEnumerable) if (!property.isEnumerable)
HandleFieldEnumerable(builder, property); HandleFieldEnumerable(builder, property);
@ -227,8 +231,9 @@ namespace MapTo.Extensions
private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray<MappedMember>? otherProperties, private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray<MappedMember>? otherProperties,
string? sourceClassParameterName, string mappingContextParameterName, bool fromUpdate) 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; 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; if (property.isReadOnly && fromUpdate) continue;
@ -261,11 +266,12 @@ namespace MapTo.Extensions
private static SourceBuilder GenerateUpdateMethod(this SourceBuilder builder, MappingModel model) 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 builder
.GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName)
.WriteLine($"public void Update({model.SourceType} {sourceClassParameterName})") .WriteLine($"public void Update({targetSourceType.SourceType} {sourceClassParameterName})")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true) .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true)
.WriteClosingBracket(); .WriteClosingBracket();
@ -280,21 +286,25 @@ namespace MapTo.Extensions
return builder; return builder;
} }
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine("/// <summary>") .WriteLine("/// <summary>")
.WriteLine($"/// Updates <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties") .WriteLine($"/// Updates <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties")
.WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.") .WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.")
.WriteLine("/// </summary>") .WriteLine("/// </summary>")
.WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{model.SourceType}\"/> to use as source.</param>"); .WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{targetSourceType.SourceType}\"/> to use as source.</param>");
} }
private static SourceBuilder GenerateEnumerableJsonSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) 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 return builder
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") .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() .WriteOpeningBracket()
.WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});")
.WriteClosingBracket(); .WriteClosingBracket();

View File

@ -504,21 +504,38 @@ namespace MapTo
return null; 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 typeIdentifierName = TypeSyntax.GetIdentifierName();
var sourceTypeIdentifierName = sourceTypeSymbol.Name;
var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel); var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel);
var isTypeUpdatable = false; //IsTypeUpdatable(); var isTypeUpdatable = false; //IsTypeUpdatable();
var hasJsonExtension = false; // HasJsonExtension(); var hasJsonExtension = false; // HasJsonExtension();
var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol);
List<MappedSourceType> mappedSourceTypes = new List<MappedSourceType>();
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 mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass);
var mappedFields = GetSourceMappedFields(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()) /*if (!mappedProperties.Any())
{ {
@ -526,29 +543,17 @@ namespace MapTo
return null; 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( return new MappingModel(
SourceGenerationOptions, SourceGenerationOptions,
TypeSyntax.GetNamespace(), TypeSyntax.GetNamespace(),
TypeSyntax.Modifiers, TypeSyntax.Modifiers,
TypeSyntax.Keyword.Text, TypeSyntax.Keyword.Text,
typeIdentifierName, typeIdentifierName,
sourceTypeSymbol.ContainingNamespace.ToDisplayString(),
sourceTypeIdentifierName,
sourceTypeSymbol.ToDisplayString(),
isTypeUpdatable, isTypeUpdatable,
hasJsonExtension, hasJsonExtension,
mappedProperties, mappedSourceTypes.ToImmutableArray(),
allProperties,
mappedFields,
allFields,
isTypeInheritFromMappedBaseClass, isTypeInheritFromMappedBaseClass,
Usings, Usings);
shouldGenerateSecondaryConstructor);
} }

View File

@ -39,28 +39,34 @@ namespace MapTo
public bool IsEnumerable => EnumerableTypeArgument is not null; public bool IsEnumerable => EnumerableTypeArgument is not null;
} }
internal record MappedSourceType
(
string SourceNamespace,
string SourceTypeIdentifierName,
string SourceTypeFullName,
ImmutableArray<MappedMember> SourceProperties,
ImmutableArray<MappedMember> SourceFields,
ImmutableArray<MappedMember> TypeProperties,
ImmutableArray<MappedMember> TypeFields,
bool GenerateSecondaryConstructor
)
{
public string SourceType => SourceTypeFullName;
}
internal record MappingModel( internal record MappingModel(
SourceGenerationOptions Options, SourceGenerationOptions Options,
string? Namespace, string? Namespace,
SyntaxTokenList Modifiers, SyntaxTokenList Modifiers,
string Type, string Type,
string TypeIdentifierName, string TypeIdentifierName,
string SourceNamespace,
string SourceTypeIdentifierName,
string SourceTypeFullName,
bool IsTypeUpdatable, bool IsTypeUpdatable,
bool IsJsonExtension, bool IsJsonExtension,
ImmutableArray<MappedMember> SourceProperties, ImmutableArray<MappedSourceType> MappedSourceTypes,
ImmutableArray<MappedMember> TypeProperties,
ImmutableArray<MappedMember> SourceFields,
ImmutableArray<MappedMember> TypeFields,
bool HasMappedBaseClass, bool HasMappedBaseClass,
ImmutableArray<string> Usings, ImmutableArray<string> Usings
bool GenerateSecondaryConstructor );
)
{
public string SourceType => SourceTypeFullName;
}
internal record SourceGenerationOptions( internal record SourceGenerationOptions(
AccessModifier ConstructorAccessModifier, AccessModifier ConstructorAccessModifier,

View File

@ -22,8 +22,10 @@ namespace MapTo.Sources
.WriteLine($"partial record {model.TypeIdentifierName}") .WriteLine($"partial record {model.TypeIdentifierName}")
.WriteOpeningBracket(); .WriteOpeningBracket();
var targetSourceType = model.MappedSourceTypes[0];
// Class body // Class body
if (model.GenerateSecondaryConstructor) if (targetSourceType.GenerateSecondaryConstructor)
{ {
builder builder
.GenerateSecondaryConstructor(model) .GenerateSecondaryConstructor(model)
@ -52,7 +54,9 @@ namespace MapTo.Sources
private static SourceBuilder GenerateSecondaryConstructor(this SourceBuilder builder, MappingModel model) 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) if (model.Options.GenerateXmlDocument)
{ {
@ -65,17 +69,19 @@ namespace MapTo.Sources
} }
return builder 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}) {{ }}"); .WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}");
} }
private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model) 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"; const string mappingContextParameterName = "context";
builder builder
.WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {model.SourceType} {sourceClassParameterName})") .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {targetSourceType.SourceType} {sourceClassParameterName})")
.Indent() .Indent()
.Write(": this("). .Write(": this(").
@ -96,9 +102,11 @@ namespace MapTo.Sources
private static SourceBuilder WriteProperties(this SourceBuilder builder, MappingModel model, string sourceClassParameterName, private static SourceBuilder WriteProperties(this SourceBuilder builder, MappingModel model, string sourceClassParameterName,
string mappingContextParameterName) 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.TypeConverter is null)
{ {
if (property.IsEnumerable) if (property.IsEnumerable)
@ -123,7 +131,7 @@ namespace MapTo.Sources
$"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})"); $"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})");
} }
if (i < model.SourceProperties.Length - 1) if (i < targetSourceType.SourceProperties.Length - 1)
{ {
builder.Write(", "); builder.Write(", ");
} }
@ -134,16 +142,17 @@ namespace MapTo.Sources
private static SourceBuilder GenerateFactoryMethod(this SourceBuilder builder, MappingModel model) 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 return builder
.GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName)
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]")
.WriteLine( .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() .WriteOpeningBracket()
.WriteLine( .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(); .WriteClosingBracket();
} }
@ -153,22 +162,25 @@ namespace MapTo.Sources
{ {
return builder; return builder;
} }
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine("/// <summary>") .WriteLine("/// <summary>")
.WriteLine($"/// Creates a new instance of <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties") .WriteLine($"/// Creates a new instance of <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties")
.WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.") .WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.")
.WriteLine("/// </summary>") .WriteLine("/// </summary>")
.WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{model.SourceType}\"/> to use as source.</param>") .WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{targetSourceType.SourceType}\"/> to use as source.</param>")
.WriteLine( .WriteLine(
$"/// <returns>A new instance of <see cred=\"{model.TypeIdentifierName}\"/> -or- <c>null</c> if <paramref name=\"{sourceClassParameterName}\"/> is <c>null</c>.</returns>"); $"/// <returns>A new instance of <see cred=\"{model.TypeIdentifierName}\"/> -or- <c>null</c> if <paramref name=\"{sourceClassParameterName}\"/> is <c>null</c>.</returns>");
} }
private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model)
{ {
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine( .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() .WriteOpeningBracket()
.GenerateSourceTypeExtensionMethod(model) .GenerateSourceTypeExtensionMethod(model)
.WriteClosingBracket(); .WriteClosingBracket();
@ -176,13 +188,15 @@ namespace MapTo.Sources
private static SourceBuilder GenerateSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) 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 return builder
.GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName)
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]")
.WriteLine( .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() .WriteOpeningBracket()
.WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});")
.WriteClosingBracket(); .WriteClosingBracket();