C# Source Generator which redirects all interface-calls to one or more backing members. Source code can be generated for a class
, record
, or struct
. It can be generated automatically or by a custom template (scriban, liquid).
Manually written source:
interface IPrintable
{
void Print();
}
public partial class Person : IPrintable
{
[BeaKona.AutoInterface]
private readonly IPrintable aspect1 = new PersonPrinterV1();
}
Auto-generated accompanying source:
partial class Person
{
void IPrintable.Print() => this.aspect1.Print();
}
In this example PersonPrinterV1
does not implement IPrintable
but does have all members that are required by that interface.
Manually written source:
interface IPrintable
{
void Print();
}
class PersonPrinterV1
{
void Print() { ... }
}
public partial class Person
{
[BeaKona.AutoInterface(typeof(IPrintable))]
private readonly PersonPrinterV1 aspect1 = new PersonPrinterV1();
}
Auto-generated accompanying source:
partial class Person : IPrintable
{
void IPrintable.Print() => this.aspect1.Print();
}
Manually written source:
interface IPrintable
{
void Print();
}
public partial class Person : IPrintable
{
// add file mytemplate.scriban in your VS project
// and set it's build action to: 'C# analyzer additional file'
[BeaKona.AutoInterface(TemplateFileName = "mytemplate.scriban")]
private readonly IPrintable? aspect1 = null;
}
Auto-generated accompanying source:
partial class Person
{
..generated from file..
}
Partial template can be defined inline (from string) or from file.
Manually written source:
interface IPrintable
{
int Length { get; }
int Count { get; }
void Print1();
void Print2();
}
public partial class Person : IPrintable
{
private void LogDebug(string name) { }
[BeaKona.AutoInterface]
[BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.PropertyGetter,
Filter = "Length", Language = "scriban", Body = "return 1;")]
[BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.Method,
Filter = "Print(\\d)?", Body="LogDebug(nameof({{interface}}.{{name}})); {{expression}};")]
private readonly IPrintable? aspect1 = new PrinterV1();
}
Auto-generated accompanying source:
partial class Person
{
int IPrintable.Length
{
return 1;
}
int IPrintable.Count => this.aspect1!.Count;
void IPrintable.Print1()
{
LogDebug(nameof(IPrintable.Print1));
this.aspect1!.Print1();
}
void IPrintable.Print2()
{
LogDebug(nameof(IPrintable.Print2));
this.aspect1!.Print2();
}
}
Other examples can be found in wiki.
---