DecoratorGenerator by Leopoldo Fu
NuGet / site data
Details
Info
Name: DecoratorGenerator
Source generator for decorator pattern boilerplate code in C#.
When implementing the decorator pattern in C#, it requires adding boilerplate code for every interface that needs to support decorators, namely the abstract class. Boilerplate is tedious to write and error-prone. This source generator solves this problem by automatically generating the abstract class. It only needs to be told which interfaces it should generate the abstract class for.
Author: Leopoldo Fu
NuGet: https://www.nuget.org/packages/DecoratorGenerator/
You can find more details at https://github.com/CodingFlow/decorator-generator
Author
Leopoldo Fu 
Original Readme
Decorator Generator
Source generator for decorator pattern boilerplate code in C#.
When implementing the decorator pattern in C#, it requires adding boilerplate code for every interface that needs to support decorators, namely the abstract class. Boilerplate is tedious to write and error-prone. This source generator solves this problem by automatically generating the abstract class. It only needs to be told which interfaces it should generate the abstract class for.

Getting Started
Installation
Add the library via NuGet to the project(s) that you want to auto-generate abstract decorator classes for:
- Either via Project > Manage NuGet Packages... / Browse / search for decorator-generator / Install
- Or by running a command in the Package Manager Console
Install-Package DecoratorGenerator
Usage
Add a Decorate attribute to the interface:
using DecoratorGenerator;
namespace SampleLibrary;
[Decorate]
public interface ICat
{
string Meow();
}
Since this library is an incremental source generator, the abstract class should be generated after saving the changes to interface's file. The generated class will be named after the interface, but without the I prefix. In this case, since the interface is ICat the class will be CatDecorator. Then create your decorator class as usual:
namespace SampleLibrary;
public class BarkingCat : CatDecorator
{
public BarkingCat(ICat cat) : base(cat)
{
}
public override string Meow()
{
return $"woof woof - {base.Meow()}";
}
}
Example usage of the decorator:
using SampleLibrary;
namespace SampleApp;
partial class Program
{
static void Main(string[] args)
{
var cat = new BarkingCat(new Cat());
var sound = cat.Meow();
Console.WriteLine(sound);
}
}
Configuration
List of Target Interfaces in a Config file
To generate decorator abstract classes for third party interfaces, Decorator Generator will look for a struct named WrapperList and generate classes of the types in the fields of the WrapperList:
using Amazon.DynamoDBv2.DataModel;
public struct WrapperList
{
// name the field whatever you want, the name isn't used, only the type is used.
IDynamoDBContext dynamoDBContext;
}
In this case, it will generate a class for IDynamoDBContext called DynamoDBContextDecorator. This feature will also work for your own interfaces if you prefer this approach instead of using the attribute.
About
adding decorator for classes/ interfaces
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
- Person.cs
- IPerson.cs
- LogPerson.cs
This is the CSharp Project that references DecoratorGenerator
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DecoratorGenerator" Version="0.3.0" />
</ItemGroup>
</Project>
This is the use of DecoratorGenerator in Program.cs
// See https://aka.ms/new-console-template for more information
using DecoratorDemo;
Console.WriteLine("Hello, World!");
IPerson person = new Person();
person = new LogPerson(person);
person.FirstName = "Andrei";
person.LastName = "Ignat";
Console.WriteLine(person.FullName());
var birthDate = new DateTime(1970, 4, 16);
var age = await person.CalculateAgeAsync(birthDate);
Console.WriteLine($"Age is {age}");
This is the use of DecoratorGenerator in Person.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace DecoratorDemo;
internal class Person : IPerson
{
public string FirstName \{ get; set; \} = string.Empty;
public string LastName \{ get; set; \} = string.Empty;
public string FullName()
{
return $"{FirstName} {LastName}";
}
public async Task<int> CalculateAgeAsync(DateTime birthDate)
{
await Task.Delay(100); // Simulate async work
var today = DateTime.Today;
var age = today.Year - birthDate.Year;
if (birthDate.Date > today.AddYears(-age)) age--;
return age;
}
}
This is the use of DecoratorGenerator in IPerson.cs
using DecoratorGenerator;
using System;
using System.Collections.Generic;
using System.Text;
namespace DecoratorDemo;
[Decorate]
public interface IPerson
{
public string FirstName \{ get; set; }
public string LastName \{ get; set; }
public string FullName();
public Task<int> CalculateAgeAsync(DateTime birthDate);
}
This is the use of DecoratorGenerator in LogPerson.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace DecoratorDemo;
internal class LogPerson : PersonDecorator
{
public LogPerson(IPerson person) : base(person)
{
}
public override string FirstName
{
get
{
Console.WriteLine($"FirstName getter called, returning {base.FirstName}");
return base.FirstName;
}
set
{
Console.WriteLine($"FirstName setter called, setting value to {value}");
base.FirstName = value;
}
}
public override string FullName()
{
Console.WriteLine($"FullName() called for {FirstName} {LastName}" );
return base.FullName();
}
public override async Task<int> CalculateAgeAsync(DateTime birthDate)
{
Console.WriteLine($"CalculateAgeAsync called with birthDate: {birthDate.ToShortDateString()}");
return await base.CalculateAgeAsync(birthDate);
}
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- PersonDecorator.generated.cs
// <auto-generated/>
#nullable restore
namespace DecoratorDemo;
public abstract class PersonDecorator : IPerson
{
private IPerson person;
protected PersonDecorator(IPerson person) {
this.person = person;
}
public virtual string FirstName \{ get => person.FirstName; set => person.FirstName = value; }
public virtual string LastName \{ get => person.LastName; set => person.LastName = value; }
public virtual string FullName() {
return person.FullName();
}
public virtual System.Threading.Tasks.Task<int> CalculateAgeAsync(System.DateTime birthDate) {
return person.CalculateAgeAsync(birthDate);
}
}
Useful
Download Example (.NET C#)
Share DecoratorGenerator
https://ignatandrei.github.io/RSCG_Examples/v2/docs/DecoratorGenerator
Category "Decorator" has the following generators:
1 DecoratorGenerator
2025-11-10