Letzten Herbst saß ich beim Kickoff mit einem Maschinenbauer aus dem Großraum Stuttgart. 180 Mitarbeitende, eine selbst entwickelte .NET-Webanwendung für Auftragssteuerung, drei Entwickler intern — und ein frisch eingeführtes Konfigurationssystem, das der Noch-Senior-Dev kurz vor seinem Abgang "modernisiert" hatte. Das Ergebnis: Niemand mehr im Team verstand, warum sich die App für Kunden aus der Schweiz anders verhielt als für Kunden aus Deutschland. Der Code war technisch korrekt. Er war nur für ein Team von drei Leuten mit einem Nachfolger, der gerade frisch aus der Ausbildung kam, schlicht zu abstrakt.
Genau an diesen Fall musste ich denken, als ich Andrew Locks neuen Beitrag über Microsoft.Extensions.Options.Contextual gelesen habe.
Was Andrew Lock erklärt
Andrew Lock — falls du ihn nicht kennst: einer der verlässlichsten .NET-Autoren im englischsprachigen Raum, kein Hype, immer Substanz — hat sich eine wenig bekannte Bibliothek aus den offiziellen Microsoft-Repositories vorgenommen: Microsoft.Extensions.Options.Contextual. Das Paket ist bis heute im Preview-Status (aktuelle Version zum Zeitpunkt des Artikels: 10.4.0-preview.1.26160.2) und taucht in keiner anderen First-Party-.NET-Library auf.
Die Idee dahinter: Du willst dein bekanntes Options-Muster aus IOptions<T> nutzen, aber die konkreten Werte sollen sich je nach Laufzeit-Kontext unterscheiden — zum Beispiel zeigt deine App für US-Nutzer Temperaturen in Fahrenheit, für deutsche Nutzer in Celsius. Statt das per if-Kette im Code zu lösen, definierst du ein Kontext-Objekt (AppContext mit einer Country-Property), markierst es mit einem Source-Generator-Attribut ([OptionsContext]), implementierst einen IOptionsContextReceiver und registrierst einen Konfigurations-Handler. Das Framework zieht dann zur Laufzeit die richtigen Optionen anhand des übergebenen Kontexts. Andrew erklärt das Schritt für Schritt und kommt am Ende zu einem ehrlichen Fazit: Das Paket ist interessant, aber ob man es einsetzen sollte, hängt stark vom Anwendungsfall ab.
Wie das im Mittelstand wirklich landet
Ich sage es direkt: Für 70 bis 80 Prozent der .NET-Projekte, die ich in KMU-Mandaten sehe, ist dieses Muster Overkill.
Nicht weil die Idee schlecht ist. Die Idee ist gut. Das Problem ist der Preis, den du zahlst — nicht in Euro, sondern in Komplexität. Und Komplexität ist im Mittelstand die teuerste Währung überhaupt, weil du dort meistens keine drei Senior-Devs hast, die eine Abstraktion wartungsarm halten.
Lass mich konkret werden. Ein typisches KMU-Szenario, in dem du mit kontext-abhängiger Konfiguration konfrontiert wirst, sieht so aus:
- Zwei Mandanten (z. B. "DE" und "CH") mit leicht unterschiedlichen Geschäftsregeln
- Unterschiedliche Feature-Flags je nach Kundenpaket (Basic vs. Premium)
- Sprache und Datumsformat je nach Browser-Locale
Für diese drei Fälle braucht du kein Source-Generator-Attribut. Du brauchst:
-
Für Mandanten-Unterschiede: Eine saubere
TenantSettings-Klasse, die du perIHttpContextAccessorund einem simplen Tenant-Resolver aus der DB oder einer JSON-Config ziehst. Das sind 40 Zeilen Code, keine externe Preview-Dependency, und dein Junior-Dev versteht es nach 20 Minuten Einlesen. -
Für Feature-Flags: Entweder ein etabliertes Tool wie Unleash (Open Source, self-hosted, funktioniert ab ca. 5 Entwicklern) oder — in kleinen Teams — eine einfache
Dictionary<string, bool>-Konfiguration aus derappsettings.json, die du per Deployment-Pipeline pro Umgebung befüllst. -
Für Locale: Das löst ASP.NET Core seit Jahren nativ mit
RequestLocalizationMiddleware. Da brauchst du überhaupt nichts Externes.
Das ist keine Kritik an Andrew Locks Beitrag — der ist technisch präzise und fair. Es ist eine Ergänzung, die im .NET-zentrierten Blickwinkel oft fehlt: Der Aufwand, ein neues Abstraktionsmuster einzuführen, ist im KMU nicht nur der initiale Implementierungsaufwand. Es ist der Einarbeitungsaufwand für jeden nachfolgenden Entwickler, die Debuggbarkeit wenn etwas schiefgeht, und das Risiko, auf ein Preview-Paket angewiesen zu sein, das — wie Andrew selbst anmerkt — von Microsoft selbst nicht eingesetzt wird.
Ein Paket, das nie aus dem Preview-Status rausgekommen ist und von keiner First-Party-Library verwendet wird, hat in einem KMU-Produktivsystem nichts zu suchen. Das ist keine dogmatische Regel. Das ist gelebtes Risikomanagement.
Wann lohnt sich der Blick trotzdem?
Es gibt exakt einen Fall im Mittelstand, wo ich Microsoft.Extensions.Options.Contextual zumindest ernsthaft evaluieren würde: Wenn du eine Multi-Tenant-SaaS-Plattform baust, bei der sich Konfigurationsdimensionen zur Compile-Zeit nicht vorhersagen lassen und Kontext-Objekte komplex und typisiert bleiben müssen.
Das klingt abstrakt, ist es aber nicht. Konkret: Wenn du heute 15 Mandanten hast und jeder davon potentiell 8–10 unterschiedliche Options-Werte mitbringt, fängst du an, mit Named Options (IOptionsSnapshot<T>) gegen Wände zu rennen. Dann ist das Muster hinter Contextual — nicht zwingend diese spezifische Library — der richtige Denkansatz.
In dem Fall würde ich aber den Source-Generator-Ansatz aus dem Paket als Inspiration nehmen und das Muster selbst implementieren. Drei Interfaces, ein Service, fertig. Keine Preview-Abhängigkeit, volle Kontrolle, ein Junior-Dev kann es lesen.
Wenn du hingegen sagst: "Wir haben eine App, die global deployed wird, und wir müssen zur Laufzeit für jeden Request entscheiden, ob Fahrenheit oder Celsius" — dann ist das in einem KMU-Kontext fast immer ein Zeichen, dass die Produktanforderungen noch nicht sauber definiert sind. Löse das zuerst.
Meine konkrete Empfehlung
Lies Andrew Locks Artikel. Ernsthaft — er ist gut, und das Verständnis des Musters hilft dir, bessere Entscheidungen zu treffen, auch wenn du die Library nie einsetzt.
Setz Microsoft.Extensions.Options.Contextual aber nicht in Produktion ein, solange:
- das Paket Preview-Status hat
- dein Team unter 5 .NET-Entwickler zählt
- du keine explizite Multi-Tenant-Anforderung mit dynamischen Kontext-Dimensionen hast
Für alles andere: IOptionsSnapshot<T> mit Named Options reicht. Oder ein einfacher Tenant-Resolver mit Dictionary-Lookup. Beides ist in einer Stunde implementiert, in fünf Minuten erklärt, und in zwei Jahren noch von deinem Nachfolger verstanden.
Der vollständige Original-Beitrag von Andrew Lock: Configuring contextual options with Microsoft.Extensions.Options.Contextual
Wenn du gerade vor einer ähnlichen Architekturentscheidung stehst und wissen willst, ob das Muster für euren konkreten Fall das Richtige ist — oder ob ihr euch da gerade etwas Unnötiges einhandelt: → 30 Min Klartext-Sparring
— Bernhard