Gobie DevLog 2 - Simple C# Source Generation
In the last post about Gobie I showed the first proof of concept. Today we have a bit of an expanded feature set to show which allows for simpler template declaration.
Updates
- Support both Fields and Classes as generator targets.
- Provide pre-defined data to the template, like
ClassName
orFieldName
so users don’t need to provide it. - Allow formatting options
pascal
andcamel
to be used in the templates.
Current Status
Just to be clear, this is currently not usable for anything other than a demo. It isn’t stable and the feature set is much too limited.
Demo
Just like last time we are generating an encapsulated field, but in this case we have a more realistic syntax. The field itself is declared by the user, and annotated with our generator attribute.
We rely on two default parameters FieldName
and FieldGenericType
instead of explicitly providing those values. Additionally we use the
formatting helpers like {{ FieldName : pascal}}
which will take the input books
and output Books
in the rendered template.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public sealed class EncapsulatedCollectionGenerator : GobieFieldGenerator
{
[GobieTemplate]
private const string EncapsulationTemplate =
@"
public System.Collections.Generic.IEnumerable<{{FieldGenericType}}> {{FieldName : pascal}} => {{FieldName : camel}}.AsReadOnly();
public void Add{{ FieldName : pascal }}({{FieldGenericType}} s)
{
{{#CustomValidator}}
if({{CustomValidator}}(s))
{
{{FieldName : camel}}.Add(s);
}
{{/CustomValidator}}
{{^CustomValidator}}
{{FieldName : camel}}.Add(s);
{{/CustomValidator}}
}";
[Required]
public string CustomValidator { get; set; } = null;
}
Defining the class that inherits from GobieFieldGenerator
tells the generator to create the marker attribute EncapsulatedCollectionAttribute
which we can use below. The usage of the attribute is shown below.
1
2
3
4
5
6
7
public partial class Author
{
[EncapsulatedCollection(nameof(ValidateBooks))]
private readonly List<string> books = new();
public bool ValidateBooks(string s) => s.Length > 0;
}
The generated output is shown below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Models
{
public partial class Author
{
public System.Collections.Generic.IEnumerable<string> Books => books.AsReadOnly();
public void AddBooks(string s)
{
if (ValidateBooks(s))
{
books.Add(s);
}
}
}
}
Feedback
I am very interested in feedback. Feel free to drop a note in the comments here or open an issue with your thoughts in the project repo
Leave a Comment
Your email address will not be published. Required fields are marked *