-
-
Save explorer14/c4e75cd2d3dcd7f24092b74164504554 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Generator] | |
public class DtoGenerator : ISourceGenerator | |
{ | |
public void Execute(GeneratorExecutionContext context) | |
{ | |
var targetTypeTracker = context.SyntaxContextReceiver as TargetTypeTracker; | |
var codeBuilder = new StringBuilder(); | |
foreach (var typeNode in targetTypeTracker.TypesNeedingDtoGening) | |
{ | |
// Use the semantic model to get the symbol for this type | |
var typeNodeSymbol = context.Compilation | |
.GetSemanticModel(typeNode.SyntaxTree) | |
.GetDeclaredSymbol(typeNode); | |
// get the namespace of the entity class | |
var entityClassNamespace = typeNodeSymbol.ContainingNamespace?.ToDisplayString() ?? "NoNamespace"; | |
// give each DTO a name, just suffix the entity class name with "Dto" | |
var generatedDtoClassName = $"{typeNodeSymbol.Name}Dto"; | |
// Add usings | |
codeBuilder.AppendLine("using System;"); | |
codeBuilder.AppendLine("using System.Collections.Generic;"); | |
codeBuilder.AppendLine("using System.Linq;"); | |
// Add target namespace | |
codeBuilder.AppendLine($"namespace {entityClassNamespace}.Dtos"); | |
codeBuilder.AppendLine("{"); | |
// Start class | |
codeBuilder.AppendLine($"\tpublic class {generatedDtoClassName}"); | |
codeBuilder.AppendLine("\t{"); | |
// get all the properties defined in this class | |
var allProperties = typeNode.Members.OfType<PropertyDeclarationSyntax>(); | |
// for each property in the domain entity, create a corresponding property | |
// in the DTO with the same type | |
foreach (var property in allProperties) | |
codeBuilder.AppendLine($"\t\t{property.BuildDtoProperty(context.Compilation)}"); | |
// Add closing braces | |
codeBuilder.AppendLine("\t}"); | |
codeBuilder.AppendLine("}"); | |
// add the code for this DTO class to the context so it can be added to the build | |
context.AddSource(generatedDtoClassName, | |
SourceText.From(codeBuilder.ToString(), Encoding.UTF8)); | |
codeBuilder.Clear(); | |
} | |
} | |
public void Initialize(GeneratorInitializationContext context) | |
{ | |
context.RegisterForSyntaxNotifications(() => new TargetTypeTracker()); | |
} | |
} | |
internal static class SourceGenExtns | |
{ | |
internal static string BuildDtoProperty( | |
this PropertyDeclarationSyntax pds, Compilation compilation) | |
{ | |
// get the symbol for this property from the semantic model | |
var symbol = compilation | |
.GetSemanticModel(pds.SyntaxTree) | |
.GetDeclaredSymbol(pds); | |
var property = (symbol as IPropertySymbol); | |
// use the same type and name for the DTO properties as on the entity | |
return $"public {property.Type.Name()} {property.Name} {{get; set;}}"; | |
} | |
// instead of returning "System.Collections.Generic.IList<>", just condense it to "IList<>" | |
// the namespace is already added in the usings block | |
internal static string Name(this ITypeSymbol typeSymbol) => | |
typeSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); | |
} |
I have one suggestion on the code. The parameter
property
of theBuildDtoProperty
method should be namedpds
, otherwise it will conflict with theproperty
variable (row nr. 70).
// bump @explorer14
I have one suggestion on the code. The parameter
property
of theBuildDtoProperty
method should be namedpds
, otherwise it will conflict with theproperty
variable (row nr. 70).// bump @explorer14
Done! I didn't realise Thomas had commented on a gist! Thanks for the bump!🙂
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have one suggestion on the code. The parameter
property
of theBuildDtoProperty
method should be namedpds
, otherwise it will conflict with theproperty
variable (row nr. 70).