Created
May 31, 2023 19:31
-
-
Save SaahilClaypool/b1aca690f154ec0fe9ed49751988e701 to your computer and use it in GitHub Desktop.
Dapper constructor source generator
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
global using Microsoft.CodeAnalysis; | |
global using Microsoft.CodeAnalysis.CSharp.Syntax; | |
using System.Diagnostics; | |
namespace Srcgen; | |
/// <summary> | |
/// Author: Saahil Claypool | |
/// https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md | |
/// </summary> | |
[Generator] | |
public class DapperConstructorGenerator : IIncrementalGenerator | |
{ | |
public const string AttributeNameSpace = "Srcgen"; | |
public const string AttributeName = "DapperConstructorAttribute"; | |
public const string AttributeFullName = "Srcgen.DapperConstructorAttribute"; | |
public void Initialize(IncrementalGeneratorInitializationContext context) | |
{ | |
var generatorAttributes = context.SyntaxProvider.ForAttributeWithMetadataName( | |
AttributeFullName, | |
(_, _) => true, | |
(syntaxContext, _) => syntaxContext | |
).Combine(context.CompilationProvider); | |
context.RegisterSourceOutput(generatorAttributes, (sourceProductionContext, tuple) => | |
{ | |
var (generatorActivationContext, compilation) = tuple; | |
if (generatorActivationContext.TargetSymbol is not INamedTypeSymbol symbol) | |
return; | |
var constructor = symbol.Constructors.First(); | |
var parameters = constructor.Parameters.Select(p => (Type: $"{p.Type.ContainingNamespace}.{p.Type.Name}", p.Name)); | |
var defaultsString = string.Join(", ", parameters.Select(p => "default!")); | |
var source = $$""" | |
namespace {{symbol.ContainingNamespace}} | |
{ | |
public partial record {{symbol.Name}} | |
{ | |
private {{symbol.Name}}() : this({{defaultsString}}) { } | |
} | |
} | |
"""; | |
// Avoid duplicate names | |
sourceProductionContext.AddSource( | |
$"{symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted))}_{AttributeFullName}.g.cs", | |
source); | |
}); | |
context.RegisterPostInitializationOutput(callback: ctx => | |
{ | |
ctx.AddSource( | |
$"{AttributeFullName}.g.cs", | |
$$""" | |
namespace {{AttributeNameSpace}} | |
{ | |
/// <summary> | |
/// generate a constructor with all parameters set to default | |
/// this is only to be used by dapper or other serializers that require | |
/// a no parameter constructor. | |
/// </summary> | |
[System.AttributeUsage(System.AttributeTargets.Class, Inherited = false, AllowMultiple = false)] | |
sealed class {{AttributeName}} : System.Attribute | |
{ | |
public {{AttributeName}}() { } | |
} | |
} | |
""" | |
); | |
}); | |
} | |
} |
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
[Srcgen.DapperConstructor] | |
public partial record TestMe(string A, string B) | |
{ | |
public int C { get; set; } | |
} | |
/* generated | |
namespace Tasks | |
{ | |
public partial record TestResult | |
{ | |
private TestResult() : this(default!, default!) { } | |
} | |
} | |
*/ |
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
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<TargetFramework>net6.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> | |
<LangVersion>preview</LangVersion> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers"> | |
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |
<PrivateAssets>all</PrivateAssets> | |
</PackageReference> | |
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" /> | |
</ItemGroup> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
I tried to use it but I have the error "DapperConstructor" and "DapperConstructorAttribute" doesn't exist
I tried with only your generator + sample to test