Sitemap
Level Up Coding

Coding tutorials and news. The developer homepage gitconnected.com && skilled.dev && levelup.dev

Member-only story

Mixin Pattern in .NET C#: From Lisp flavors to extension members and source generators (2026)

--

Imagine developing the back office of an e-commerce site. Products, orders, coupons and assistance plans share some capabilities, but not the same ones. Products and orders must be auditable: who created and changed them, and when. Coupons must be soft-deletable, because a deleted coupon must still appear in the orders that used it. Products and blog posts must be taggable, and products versioned, because two operators editing the same price is a Monday morning classic. The first idea is the one we all learned at school: a base class.

// Naive approach - What NOT to do
public abstract class Entity { public Guid Id { get; init; } = Guid.NewGuid(); }

public abstract class AuditableEntity : Entity
{
public DateTimeOffset CreatedAt { get; set; }
public string? ModifiedBy { get; set; }
}

public abstract class SoftDeletableAuditableEntity : AuditableEntity
{
public bool IsDeleted { get; set; }
}

public abstract class TaggableSoftDeletableAuditableEntity : SoftDeletableAuditableEntity
{
public HashSet<string> Tags { get; } = [];
}

public class Product : TaggableSoftDeletableAuditableEntity { }

// And now?
// Coupon: soft-deletable and versioned, but neither auditable nor taggable
// AssistancePlan: auditable, but it already inherits from Subscription

Four capabilities make sixteen combinations, and C# gives every class one single base class. The hierarchy no longer models the domain: it models the order in…

--

--

Emanuele Longo
Emanuele Longo

Written by Emanuele Longo

.NET Software Developer driven by clean architecture and purposeful design.