Supporting 'friendly constructors'
This commit is contained in:
parent
aa5b01cdc4
commit
a6f5116656
|
@ -14,42 +14,17 @@ namespace MapTo.Extensions
|
||||||
internal static SourceCode GenerateStructOrClass(this MappingModel model, string structOrClass)
|
internal static SourceCode GenerateStructOrClass(this MappingModel model, string structOrClass)
|
||||||
{
|
{
|
||||||
const bool writeDebugInfo = false;
|
const bool writeDebugInfo = false;
|
||||||
|
|
||||||
|
List<string> constructorHeaders = new List<string>();
|
||||||
|
|
||||||
using var builder = new SourceBuilder()
|
using var builder = new SourceBuilder()
|
||||||
.WriteLine(GeneratedFilesHeader)
|
.WriteLine(GeneratedFilesHeader)
|
||||||
.WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes)
|
.WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes)
|
||||||
.WriteUsings(model.Usings)
|
.WriteUsings(model.Usings)
|
||||||
.WriteLine()
|
.WriteLine()
|
||||||
|
|
||||||
// Namespace declaration
|
// Namespace declaration
|
||||||
.WriteLine($"namespace {model.Namespace}")
|
.WriteLine($"namespace {model.Namespace}")
|
||||||
.WriteOpeningBracket();
|
.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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
builder
|
builder
|
||||||
// Class declaration
|
// Class declaration
|
||||||
|
@ -57,10 +32,10 @@ namespace MapTo.Extensions
|
||||||
.WriteOpeningBracket()
|
.WriteOpeningBracket()
|
||||||
.WriteLine()
|
.WriteLine()
|
||||||
// Class body
|
// Class body
|
||||||
.GeneratePublicConstructor(model);
|
.GeneratePublicConstructor(model, ref constructorHeaders)
|
||||||
|
.GeneratePublicConstructor(model, ref constructorHeaders, true);
|
||||||
|
|
||||||
|
|
||||||
var addedMembers = new List<MappedMember>();
|
|
||||||
|
|
||||||
if (model.IsTypeUpdatable) builder.GenerateUpdateMethod(model);
|
if (model.IsTypeUpdatable) builder.GenerateUpdateMethod(model);
|
||||||
if (model.IsJsonExtension) builder.WriteToJsonMethod(model);
|
if (model.IsJsonExtension) builder.WriteToJsonMethod(model);
|
||||||
|
|
||||||
|
@ -76,7 +51,7 @@ namespace MapTo.Extensions
|
||||||
return new(builder.ToString(), $"{model.Namespace}.{model.TypeIdentifierName}.g.cs");
|
return new(builder.ToString(), $"{model.Namespace}.{model.TypeIdentifierName}.g.cs");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model)
|
private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model, ref List<string> constructorHeaders, bool filterNonMapped = false)
|
||||||
{
|
{
|
||||||
const string mappingContextParameterName = "context";
|
const string mappingContextParameterName = "context";
|
||||||
|
|
||||||
|
@ -89,7 +64,7 @@ namespace MapTo.Extensions
|
||||||
|
|
||||||
foreach (var property in targetSourceType.TypeProperties)
|
foreach (var property in targetSourceType.TypeProperties)
|
||||||
{
|
{
|
||||||
if (!targetSourceType.SourceProperties.IsMappedProperty(property))
|
if (!targetSourceType.SourceProperties.IsMappedProperty(property) && !filterNonMapped)
|
||||||
{
|
{
|
||||||
stringBuilder.Append(", ");
|
stringBuilder.Append(", ");
|
||||||
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
|
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
|
||||||
|
@ -99,7 +74,7 @@ namespace MapTo.Extensions
|
||||||
}
|
}
|
||||||
foreach (var property in targetSourceType.TypeFields)
|
foreach (var property in targetSourceType.TypeFields)
|
||||||
{
|
{
|
||||||
if (!targetSourceType.SourceFields.IsMappedProperty(property))
|
if (!targetSourceType.SourceFields.IsMappedProperty(property) && !filterNonMapped)
|
||||||
{
|
{
|
||||||
stringBuilder.Append(", ");
|
stringBuilder.Append(", ");
|
||||||
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
|
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
|
||||||
|
@ -109,10 +84,25 @@ namespace MapTo.Extensions
|
||||||
|
|
||||||
var readOnlyPropertiesArguments = stringBuilder.ToString();
|
var readOnlyPropertiesArguments = stringBuilder.ToString();
|
||||||
|
|
||||||
|
var constructorHeader =
|
||||||
|
$"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}";
|
||||||
|
|
||||||
|
|
||||||
|
bool hasAlreadyConstructor = false;
|
||||||
|
|
||||||
|
foreach (var header in constructorHeaders)
|
||||||
|
{
|
||||||
|
if(constructorHeader.Contains(header)) hasAlreadyConstructor = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAlreadyConstructor) continue;
|
||||||
|
|
||||||
|
constructorHeaders.Add(constructorHeader);
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.WriteLine($"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}")
|
.WriteLine(constructorHeader)
|
||||||
.WriteOpeningBracket()
|
.WriteOpeningBracket()
|
||||||
.WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false);
|
.WriteAssignmentMethod(model, filterNonMapped ? null : otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, filterNonMapped);
|
||||||
|
|
||||||
builder.WriteClosingBracket()
|
builder.WriteClosingBracket()
|
||||||
.WriteLine();
|
.WriteLine();
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace MapTo
|
||||||
|
|
||||||
var compilation = context.Compilation
|
var compilation = context.Compilation
|
||||||
.AddSource(ref context, UseUpdateAttributeSource.Generate(options))
|
.AddSource(ref context, UseUpdateAttributeSource.Generate(options))
|
||||||
|
.AddSource(ref context, AddDataAttributeSource.Generate(options))
|
||||||
.AddSource(ref context, JsonExtensionAttributeSource.Generate(options))
|
.AddSource(ref context, JsonExtensionAttributeSource.Generate(options))
|
||||||
.AddSource(ref context, MapFromAttributeSource.Generate(options))
|
.AddSource(ref context, MapFromAttributeSource.Generate(options))
|
||||||
.AddSource(ref context, IgnoreMemberAttributeSource.Generate(options))
|
.AddSource(ref context, IgnoreMemberAttributeSource.Generate(options))
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
using static MapTo.Sources.Constants;
|
||||||
|
|
||||||
|
namespace MapTo.Sources
|
||||||
|
{
|
||||||
|
public class AddDataAttributeSource
|
||||||
|
{
|
||||||
|
internal const string AttributeName = "AddDataGenerator";
|
||||||
|
internal const string AttributeClassName = AttributeName + "Attribute";
|
||||||
|
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
||||||
|
|
||||||
|
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||||
|
{
|
||||||
|
using var builder = new SourceBuilder()
|
||||||
|
.WriteLine(GeneratedFilesHeader)
|
||||||
|
.WriteLine("using System;")
|
||||||
|
.WriteLine()
|
||||||
|
.WriteLine($"namespace {RootNamespace}")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine("/// Generates CRUD functions to be used with the specified database context and entity.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]")
|
||||||
|
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine($"/// Initializes a new instance of the <see cref=\"{AttributeName}Attribute\"/> class with the specified <paramref name=\"sourceType\"/>.")
|
||||||
|
.WriteLine("/// </summary>")
|
||||||
|
.WriteLine("/// <param name=\"sourceType\">The type of to map from.</param>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine($"public {AttributeName}Attribute(Type databaseContextType)")
|
||||||
|
.WriteOpeningBracket()
|
||||||
|
.WriteLine("DatabaseContextType = databaseContextType;")
|
||||||
|
.WriteClosingBracket()
|
||||||
|
.WriteLine();
|
||||||
|
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine("/// Gets the type to map from.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("public Type DatabaseContextType { get; }")
|
||||||
|
.WriteClosingBracket() // class
|
||||||
|
.WriteClosingBracket(); // namespace
|
||||||
|
|
||||||
|
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using static MapTo.Sources.Constants;
|
||||||
|
|
||||||
|
namespace MapTo.Sources
|
||||||
|
{
|
||||||
|
public class UpdateDataAttributeSource
|
||||||
|
{
|
||||||
|
internal const string AttributeName = "UpdateData";
|
||||||
|
internal const string AttributeClassName = AttributeName + "Attribute";
|
||||||
|
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
||||||
|
|
||||||
|
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||||
|
{
|
||||||
|
using var builder = new SourceBuilder()
|
||||||
|
.WriteLine(GeneratedFilesHeader)
|
||||||
|
.WriteLine("using System;")
|
||||||
|
.WriteLine()
|
||||||
|
.WriteLine($"namespace {RootNamespace}")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine("/// Generates CRUD functions to be used with the specified database context and entity.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]")
|
||||||
|
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine($"/// Initializes a new instance of the <see cref=\"{AttributeName}Attribute\"/> class with the specified <paramref name=\"sourceType\"/>.")
|
||||||
|
.WriteLine("/// </summary>")
|
||||||
|
.WriteLine("/// <param name=\"sourceType\">The type of to map from.</param>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine($"public {AttributeName}Attribute(Type databaseContextType)")
|
||||||
|
.WriteOpeningBracket()
|
||||||
|
.WriteLine("DatabaseContextType = databaseContextType;")
|
||||||
|
.WriteClosingBracket()
|
||||||
|
.WriteLine();
|
||||||
|
|
||||||
|
|
||||||
|
if (options.GenerateXmlDocument)
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteLine("/// <summary>")
|
||||||
|
.WriteLine("/// Gets the type to map from.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("public Type DatabaseContextType { get; }")
|
||||||
|
.WriteClosingBracket() // class
|
||||||
|
.WriteClosingBracket(); // namespace
|
||||||
|
|
||||||
|
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue