<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Emanuele Longo on Medium]]></title>
        <description><![CDATA[Stories by Emanuele Longo on Medium]]></description>
        <link>https://medium.com/@emanuele.longo992?source=rss-6cbbf07417e5------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*aHBcAlhxaVpPyDXujHE9gg.jpeg</url>
            <title>Stories by Emanuele Longo on Medium</title>
            <link>https://medium.com/@emanuele.longo992?source=rss-6cbbf07417e5------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 04 Nov 2026 23:30:38 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@emanuele.longo992/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Async Streams in C# 8+: From Task<List<T>> to IAsyncEnumerable and Channels]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/async-streams-in-c-8-from-task-list-t-to-iasyncenumerable-and-channels-798888bf100a?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1200/1*uPWpY5fE2cpeKK3ZMMijEQ.jpeg" width="1200"></a></p><p class="medium-feed-snippet">Collections are one of the fundamental pillars of every application. If you&#x2019;ve ever written C# code, you&#x2019;ve walked thousands of them with&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/async-streams-in-c-8-from-task-list-t-to-iasyncenumerable-and-channels-798888bf100a?source=rss-6cbbf07417e5------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/async-streams-in-c-8-from-task-list-t-to-iasyncenumerable-and-channels-798888bf100a?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/798888bf100a</guid>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[asynchronous-programming]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[best-practices]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Wed, 04 Nov 2026 16:27:59 GMT</pubDate>
            <atom:updated>2026-11-04T16:27:59.244Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Chain of Responsibility Pattern in .NET C#: From linked handlers to delegate pipelines (2026)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/chain-of-responsibility-pattern-in-net-c-from-linked-handlers-to-delegate-pipelines-2026-bfc8ae80401f?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*uQmSwav016JeUwWKgqajTw.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine developing the order approval of an e-commerce that sells to consumers and companies.</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/chain-of-responsibility-pattern-in-net-c-from-linked-handlers-to-delegate-pipelines-2026-bfc8ae80401f?source=rss-6cbbf07417e5------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/chain-of-responsibility-pattern-in-net-c-from-linked-handlers-to-delegate-pipelines-2026-bfc8ae80401f?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/bfc8ae80401f</guid>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[dotnet]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Wed, 04 Nov 2026 16:26:18 GMT</pubDate>
            <atom:updated>2026-11-04T20:29:13.270Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Command Pattern in .NET C#: From undo buttons to queued, idempotent commands (2026)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/command-pattern-in-net-c-from-undo-buttons-to-queued-idempotent-commands-2026-868e14c10e59?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*PPX2X8_J_SZ5P-MQ5-BA0g.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine developing the back-office of an e-commerce site. Every day, the operators change prices, launch discounts on whole categories and&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/command-pattern-in-net-c-from-undo-buttons-to-queued-idempotent-commands-2026-868e14c10e59?source=rss-6cbbf07417e5------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/command-pattern-in-net-c-from-undo-buttons-to-queued-idempotent-commands-2026-868e14c10e59?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/868e14c10e59</guid>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[dotnet]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Wed, 04 Nov 2026 16:24:29 GMT</pubDate>
            <atom:updated>2026-11-04T20:28:44.244Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Microkernel (Plugin) Architecture in .NET]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@emanuele.longo992/microkernel-plugin-architecture-in-net-2c6e90551edc?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*sSsCm0KtOWtIkZx9oihuuw.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine your e-commerce is open in one country, with one payment provider. Then marketing launches a new coupon every month, a second&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@emanuele.longo992/microkernel-plugin-architecture-in-net-2c6e90551edc?source=rss-6cbbf07417e5------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@emanuele.longo992/microkernel-plugin-architecture-in-net-2c6e90551edc?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/2c6e90551edc</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-design]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[software-architecture]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Wed, 04 Nov 2026 14:01:03 GMT</pubDate>
            <atom:updated>2026-11-04T14:01:03.254Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Pipes and Filters in .NET C#: From Unix pipes to Channels and async streams (2026)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@emanuele.longo992/pipes-and-filters-in-net-c-from-unix-pipes-to-channels-and-async-streams-2026-707a17a024ff?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*JCy5ISqZKaMt_Jrs1xZtlQ.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine your e-commerce is doing well. Orders arrive from your own checkout, and now also from a marketplace that sends a file every night&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@emanuele.longo992/pipes-and-filters-in-net-c-from-unix-pipes-to-channels-and-async-streams-2026-707a17a024ff?source=rss-6cbbf07417e5------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@emanuele.longo992/pipes-and-filters-in-net-c-from-unix-pipes-to-channels-and-async-streams-2026-707a17a024ff?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/707a17a024ff</guid>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[software-design]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[software-architecture]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Tue, 03 Nov 2026 14:01:01 GMT</pubDate>
            <atom:updated>2026-11-04T20:22:55.912Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Event-Driven Architecture in .NET C#: From the Observer pattern to the transactional outbox (2026)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@emanuele.longo992/event-driven-architecture-in-net-c-from-the-observer-pattern-to-the-transactional-outbox-2026-be2ec3433050?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*JjmG4W1_MbvjGqJM2XKHOg.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine your e-commerce is growing. When an order is placed, the shop must reserve the stock, prepare the shipment, send the confirmation&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@emanuele.longo992/event-driven-architecture-in-net-c-from-the-observer-pattern-to-the-transactional-outbox-2026-be2ec3433050?source=rss-6cbbf07417e5------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@emanuele.longo992/event-driven-architecture-in-net-c-from-the-observer-pattern-to-the-transactional-outbox-2026-be2ec3433050?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/be2ec3433050</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[software-design]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Mon, 02 Nov 2026 14:01:03 GMT</pubDate>
            <atom:updated>2026-11-02T14:01:03.063Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Behavioral Patterns in .NET C#: Coordinating objects and responsibilities in modern applications]]></title>
            <link>https://levelup.gitconnected.com/behavioral-patterns-in-net-c-coordinating-objects-and-responsibilities-in-modern-applications-5d6d72bc9f6b?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/5d6d72bc9f6b</guid>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Mon, 02 Nov 2026 05:13:29 GMT</pubDate>
            <atom:updated>2026-11-04T20:26:41.358Z</atom:updated>
            <content:encoded><![CDATA[<p>Creating objects and connecting them is only half of the story. Once an application is running, its objects have to <strong>collaborate</strong>: decide who handles a request, react when something changes, choose the right algorithm, remember a state and, sometimes, go back. Behavioral patterns are about exactly this: not what objects are, but <strong>how they share responsibilities and how they talk to each other</strong>.</p><p>It’s also the largest family of the Gang of Four catalog: 11 of the 23 patterns in the 1994 book are behavioral, against five creational and seven structural. If <a href="https://medium.com/p/27388d43d8e5">creational patterns</a> answer the question “how is an object born?” and <a href="https://medium.com/p/355bda5e2887">structural patterns</a> “how do objects fit together?”, behavioral patterns help us answer questions like:</p><ul><li>How do we change an algorithm at runtime without touching the code that uses it?</li><li>How do we let many objects react to an event without the sender knowing who they are?</li><li>How do we pass a request through a series of steps, each free to handle it or pass it on?</li><li>How do we turn a request into an object that can be queued, logged or undone?</li><li>How do we walk through a collection, or a tree, without exposing how it’s built?</li></ul><figure><img alt="Behavioral Patterns cover in the style of the Design Patterns series: BEHAVIORAL PATTERNS in green, with the .NET and C# badges and the topics Strategy, Observer, Command, Iterator, Chain of Responsibility, State, Visitor, Mediator, Delegates, Async" src="https://cdn-images-1.medium.com/max/1024/1*EenjT3mpnI-lLA4nuPGN7A.jpeg" /><figcaption>Behavioral Patterns .NET C#</figcaption></figure><p>But as often happens in .NET, the story of these patterns is also the story of the language. Many of them have been absorbed by C# and by the framework so deeply that we use them every day without calling them by name: foreach is an Iterator, event is an Observer, the ASP.NET Core middleware is a Chain of Responsibility.</p><p>In this series, we’ll explore the following behavioral patterns. As with the previous families, not just GoF:</p><ul><li><a href="https://medium.com/p/bfc8ae80401f"><strong>Chain of Responsibility Pattern (GoF)</strong></a><strong>:</strong> Passes a request along a chain of handlers, each of which can handle it or pass it to the next one</li><li><a href="https://medium.com/p/868e14c10e59"><strong>Command Pattern (GoF)</strong></a><strong>:</strong> Turns a request into an object, so it can be queued, logged, retried or undone</li><li><strong>Interpreter Pattern (GoF):</strong> Represents the grammar of a small language as objects, and uses them to evaluate its sentences</li><li><strong>Iterator Pattern (GoF):</strong> Traverses the elements of a collection without exposing its internal structure</li><li><strong>Mediator Pattern (GoF):</strong> Centralizes the communication between objects, so they don’t refer to each other directly</li><li><strong>Memento Pattern (GoF):</strong> Captures the state of an object so it can be restored later, without breaking encapsulation</li><li><strong>Observer Pattern (GoF):</strong> Automatically notifies many dependent objects when the state of one object changes</li><li><strong>State Pattern (GoF):</strong> Lets an object change its behavior when its internal state changes, as if it changed class</li><li><strong>Strategy Pattern (GoF):</strong> Defines a family of interchangeable algorithms and lets the client choose one at runtime</li><li><strong>Template Method Pattern (GoF):</strong> Fixes the skeleton of an algorithm in a base class and lets subclasses redefine some of its steps</li><li><strong>Visitor Pattern (GoF):</strong> Adds new operations to a structure of objects without changing their classes</li><li><strong>Null Object Pattern:</strong> Replaces null with an object that does nothing, so the caller never has to check</li><li><strong>Specification Pattern:</strong> Encapsulates a business rule in an object that can be combined with others and reused, even in database queries</li><li><strong>Event Aggregator Pattern:</strong> Collects the events of many publishers in a single place, so subscribers register only once</li></ul><p>Fourteen names are easier to keep in mind by the question each one answers:</p><figure><img alt="Map of the 14 behavioral patterns in six cards, each with the question it answers: which algorithm runs (Strategy, State, Template Method), who handles the request (Chain of Responsibility, Command, Mediator), who hears about the change (Observer, Event Aggregator), how to walk a structure (Iterator, Visitor, Interpreter), can I go back (Memento), what is the rule and what if nothing is there (Specification, Null Object)" src="https://cdn-images-1.medium.com/max/1024/1*ykDnegjzSlLH0EeYexePbA.png" /><figcaption>Behavioral patterns by the question they answer</figcaption></figure><h3>Behavioral Basics: Inheritance or composition?</h3><p>The Gang of Four split the family in two. Only the Template Method and the Interpreter are <strong>class patterns</strong>, built on inheritance; all the others are <strong>object patterns</strong>, built on composition: a Strategy is an object you plug in, an Observer one you register, a Command one you pass around. More than thirty years later, composition is the default, and in C# it has become much lighter than in the C++ of 1994, because the smallest possible object with a behavior is not a class. It’s a <strong>delegate</strong>.</p><h3>You Already Use Them: Behavioral patterns inside .NET</h3><p>Many behavioral patterns are already in the code we write every day:</p><ul><li><strong>Iterator</strong> — IEnumerable&lt;T&gt;, foreach, yield return and IAsyncEnumerable&lt;T&gt;</li><li><strong>Observer</strong> — C# events, IObservable&lt;T&gt;, INotifyPropertyChanged, IOptionsMonitor&lt;T&gt;.OnChange</li><li><strong>Strategy</strong> — IComparer&lt;T&gt;, IEqualityComparer&lt;T&gt;, the Comparison&lt;T&gt; passed to List&lt;T&gt;.Sort</li><li><strong>Template Method</strong> — BackgroundService, where you write only ExecuteAsync</li><li><strong>Chain of Responsibility</strong> — the ASP.NET Core middleware and the DelegatingHandler of HttpClient</li><li><strong>Command</strong> — ICommand in WPF and .NET MAUI, with Execute and CanExecute</li><li><strong>Visitor</strong> — ExpressionVisitor in System.Linq.Expressions and the syntax walkers of Roslyn</li><li><strong>Interpreter</strong> — the regular expression engine, which interprets your pattern as a series of instructions</li><li><strong>Null Object</strong> — NullLogger&lt;T&gt;.Instance, Stream.Null, TextWriter.Null</li><li><strong>Specification</strong> — the Expression&lt;Func&lt;T, bool&gt;&gt; predicates that EF Core translates into SQL</li></ul><p>The language took a long time to absorb them, one release at a time:</p><figure><img alt="Timeline in ten cards of the language features that absorbed the behavioral patterns: C# 1.0 events and delegates, C# 2.0 iterators, C# 3.0 lambdas and LINQ, .NET Framework 4 IObservable, C# 5.0 async await, C# 7.0 pattern matching, C# 8.0 switch expressions and IAsyncEnumerable, .NET 7 GeneratedRegex, .NET 8 keyed services and TimeProvider, and C# 15 union and closed in preview. Each card names the patterns it touched" src="https://cdn-images-1.medium.com/max/1024/1*0rAp_hIvuwEOE3-0MQ2hWg.png" /><figcaption>How C# absorbed the behavioral patterns</figcaption></figure><h3>From Hierarchies to Delegates: The functional revolution</h3><p>In their classic form, Strategy, Command and Template Method all require a small hierarchy: an interface or an abstract class, and one class per variant. Imagine calculating the shipping costs of an e-commerce site:</p><pre>// Classic: one interface, one class per algorithm<br>public interface IShippingCostStrategy<br>{<br>    decimal Calculate(Order order);<br>}<br> <br>public sealed class ExpressShipping : IShippingCostStrategy<br>{<br>    public decimal Calculate(Order order) =&gt; 9.90m + order.Items.Count * 0.50m;<br>}<br> <br>// ... StandardShipping, PickupPoint, and one class for every new rule<br> <br>// Modern: the algorithm is just a value<br>public sealed class CheckoutService(Func&lt;Order, decimal&gt; shippingCost)<br>{<br>    public decimal Total(Order order) =&gt; order.Total + shippingCost(order);<br>}<br> <br>// Usage<br>var standard = new CheckoutService(o =&gt; o.Total &gt;= 50m ? 0m : 4.90m);<br>var express = new CheckoutService(o =&gt; 9.90m + o.Items.Count * 0.50m);</pre><p>With C# 3.0 came lambdas, and that was the <strong>watershed moment</strong>: a strategy with a single method is just a function, and a function can be passed, stored and composed like any other value. LINQ is built on this idea: OrderBy(o =&gt; o.Total) receives its sorting key as a strategy. The same happened to the Command (a Func&lt;CancellationToken, Task&gt; is a command waiting to be run) and to the Template Method: ASP.NET Core cookie authentication lets you customize a step of the flow with a delegate, such as options.Events.OnRedirectToLogin, with no subclass. (If you want to find out more about delegates, events and lambdas, <a href="https://medium.com/p/0c6e72172ee2">click here</a>.)</p><p><strong>But beware!</strong> A lambda has no name and no dependencies of its own. When the algorithm needs services from the DI container, has more than one method, or must be chosen with a key read from the configuration, the class comes back. Keyed services, introduced in .NET 8, are the modern way to register ExpressShipping with the key &quot;express&quot; and inject it where it&#39;s needed. (If you want to find out more about keyed services, <a href="https://medium.com/p/da72bc4d53a3">click here</a>.)</p><p>What do you think? Have delegates replaced the classic Strategy in your code, or do you still prefer one class per algorithm? Leave a comment with your opinion.</p><h3>Observer and Iterator: Events, streams and IAsyncEnumerable</h3><p>C# embraced the Observer from day one: since C# 1.0, the event keyword and multicast delegates give every class a list of subscribers, with += and -= to join and leave it. In .NET Framework 4, IObservable&lt;T&gt; and IObserver&lt;T&gt; added what events lacked: the end of the stream (OnCompleted), its errors (OnError), and a subscription that is itself an IDisposable. On top of them, Reactive Extensions (the System.Reactive package) lets you filter, throttle and combine notifications like a LINQ query.</p><p>The pattern is everywhere, but it brings some <strong>insidious</strong> traps:</p><ul><li>a subscriber that never unsubscribes lives as long as the publisher: the classic memory leak of events;</li><li>an exception in one handler stops the handlers after it;</li><li>an async void handler throws exceptions that the publisher cannot catch.</li></ul><p>The Iterator had a similar destiny. The GoF version required a dedicated class with First, Next, IsDone and CurrentItem. C# made it disappear: C# 1.0 gave us IEnumerable and foreach, C# 2.0 yield return, with the compiler writing the state machine for us. LINQ, in C# 3.0, is a chain of iterators that produce values only when someone asks for them: the famous <strong>deferred execution</strong>. The last step came with C# 8.0 and .NET Core 3.0: IAsyncEnumerable&lt;T&gt; and await foreach, iterators that can wait for I/O between one element and the next. Here&#39;s one that hides the pagination of a remote API:</p><pre>public sealed class OrderFeed(HttpClient http)<br>{<br>    public async IAsyncEnumerable&lt;OrderDto&gt; ReadAllAsync(<br>        [EnumeratorCancellation] CancellationToken cancellationToken = default)<br>    {<br>        string? next = &quot;orders?page=1&quot;;<br> <br>        while (next is not null)<br>        {<br>            var page = await http.GetFromJsonAsync&lt;OrderPage&gt;(next, cancellationToken)<br>                ?? throw new InvalidOperationException(&quot;Empty response from the server&quot;);<br> <br>            foreach (var order in page.Items)<br>            {<br>                yield return order; // the consumer sees orders, never pages<br>            }<br> <br>            next = page.NextLink;<br>        }<br>    }<br>}</pre><p>The consumer writes a simple await foreach and never sees a page. The [EnumeratorCancellation] attribute is the detail that makes the difference: the token passed with WithCancellation reaches the iterator, which stops between one page and the next. (If you want to find out more about async streams, <a href="https://medium.com/p/798888bf100a">click here</a>.)</p><h3>The Middleware Pipeline: Chain of Responsibility at the heart of ASP.NET Core</h3><p>In the Decorator article, we saw that the ASP.NET Core pipeline is both a decorator and a chain of responsibility, and that the difference fits in one line: await next(context). (If you want to find out more about the Decorator, <a href="https://medium.com/p/111ace6e8658">click here</a>.) When a component can decide <strong>not</strong> to call it, it&#39;s a handler of a Chain of Responsibility:</p><pre>// Each handler decides: handle the request, or pass it on<br>app.Use(async (context, next) =&gt;<br>{<br>    if (app.Configuration.GetValue&lt;bool&gt;(&quot;Shop:Maintenance&quot;))<br>    {<br>        context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;<br>        await context.Response.WriteAsync(&quot;The shop is under maintenance, please come back soon!&quot;);<br>        return; // short-circuit: the rest of the chain never runs<br>    }<br> <br>    await next(context); // pass the request to the next handler<br>});<br> <br>app.MapGet(&quot;/orders/{id}&quot;, (string id) =&gt; Results.Ok(new { id, status = &quot;Confirmed&quot; }));</pre><p>Here’s the thing: the order is part of the design. A handler in the wrong position, or one that forgets to call next, silently changes the behavior of the whole application.</p><h3>Pattern Matching and Closed Hierarchies: State and Visitor rethought</h3><p>The Visitor is the most ceremonious of the GoF patterns: every class gets an Accept method, the visitor gets one Visit method per type, and the double dispatch is hard to explain on the first attempt. The framework still uses it where it makes sense: huge, open trees like expression trees and the Roslyn syntax tree.</p><p>For the hierarchies of our domain, pattern matching offers a more direct road. It arrived in C# 7.0 and grew with the switch expressions of C# 8.0 and the relational and logical patterns of C# 9: the operation lives in one switch expression over the types. The same applies to the State pattern, which classically spreads the state machine over one class per state. With records and tuple patterns, the transitions fit in one table:</p><pre>public abstract record OrderState;<br>public sealed record Pending : OrderState;<br>public sealed record Paid(DateTimeOffset PaidAt) : OrderState;<br>public sealed record Shipped(string TrackingCode) : OrderState;<br>public sealed record Cancelled(string Reason) : OrderState;<br> <br>public abstract record OrderEvent;<br>public sealed record PaymentReceived(DateTimeOffset At) : OrderEvent;<br>public sealed record ParcelShipped(string TrackingCode) : OrderEvent;<br>public sealed record CancelRequested(string Reason) : OrderEvent;<br> <br>public static class OrderWorkflow<br>{<br>    // The whole state machine in one table<br>    public static OrderState Next(OrderState state, OrderEvent @event) =&gt; (state, @event) switch<br>    {<br>        (Pending, PaymentReceived p) =&gt; new Paid(p.At),<br>        (Paid, ParcelShipped s) =&gt; new Shipped(s.TrackingCode),<br>        (Pending or Paid, CancelRequested c) =&gt; new Cancelled(c.Reason),<br>        _ =&gt; throw new InvalidOperationException(<br>            $&quot;Invalid transition: {state.GetType().Name} + {@event.GetType().Name}&quot;)<br>    };<br>}</pre><p>The classic State is still the right choice when each state carries a lot of its own behavior. But when the transitions are the heart of the problem, the table is <strong>self-documenting</strong>: you read it, and you know the rules of the order.</p><p>The missing piece has always been exhaustiveness: with an open hierarchy, the compiler can’t know all the cases, and a _ arm can hide the ones we forgot. C# 15 addresses it with union types and closed hierarchies. A closed class can be derived only inside its own assembly, so the compiler knows every direct descendant, and a switch that handles all of them needs no default arm. C# 15 comes with .NET 11, which at the time of writing is a release candidate, with the release expected in November 2026: for now, it&#39;s a preview of what these hierarchies will look like. Union types, closed hierarchies and the whole history of pattern matching will each have their own C# Insights.</p><h3>Mediators and Async: Behaviors that cross boundaries</h3><p>The GoF Mediator was born for a dialog box: instead of letting every widget know all the others, they all talk to a director. In .NET the idea took a different shape: <strong>in-process mediators</strong>, where you send a request object and the mediator finds its handler. For years MediatR has been the reference library; in July 2025 its author announced commercial editions of MediatR and AutoMapper, a good moment to ask whether we need a mediator at all.</p><p>A mediator gives you one place for cross-cutting concerns, but the price is indirection: Go to Definition no longer takes you to the code that runs. The alternatives range from injecting the handler directly to mediator libraries based on source generators. The Event Aggregator applies the same idea to notifications, and when messages cross the boundary of the process, we enter the Integration patterns, a family of their own.</p><p>The GoF interfaces were synchronous: Execute(), Update(), HandleRequest(). Today almost every behavior does I/O: a strategy calls a payment API, a command writes to the database, an observer sends an email. Since C# 5.0, this has changed the shape of the whole family:</p><ul><li><strong>Signatures</strong> — Task or ValueTask, with a CancellationToken as part of the contract</li><li><strong>Chains</strong> — the token flows through every link, and every link must respect it</li><li><strong>Observers</strong> — classic events don’t handle asynchronous work well, and async void is always around the corner</li></ul><p>A behavior that ignores cancellation keeps working for a user who’s already gone. With .NET 11, Runtime Async (not final yet) moves async/await support into the runtime itself, for cleaner stack traces and lower overhead; it will have its own C# Insights.</p><h3>Testability: Behaviors you can verify</h3><p>Behavioral patterns are good friends of tests, because each of them extracts a piece of behavior into a replaceable unit. A strategy passed as a delegate needs no mock, just a lambda, and a state table is tested by feeding it events.</p><p>The most hidden collaborator of many behaviors is time: carts that expire, coupons that end, retries that wait. Since .NET 8, TimeProvider makes it injectable, and the FakeTimeProvider of the Microsoft.Extensions.TimeProvider.Testing package lets a test move it forward with Advance. <strong>But beware!</strong> The more indirection we add (events, mediators, long pipelines), the less a unit test tells us about the whole flow: decoupled behaviors need integration tests that put them back together.</p><h3>Future Trends: Generated code and orchestrated behaviors</h3><p>Two trends are reshaping this family. The first is <strong>source generators</strong>: behaviors once resolved at runtime with reflection are now resolved at build time. (If you want to find out more about source generators, <a href="https://medium.com/p/e6a5a5d313bf">click here</a>.) The regular expression engine is the perfect example of an Interpreter that evolved: by default a pattern is interpreted at runtime, with RegexOptions.Compiled it becomes IL, and since .NET 7 [GeneratedRegex] turns it into C# during the build, code you can open and follow.</p><p>The second trend is <strong>AI agents</strong>. When a language model decides at runtime which tool to call, each call is a command that can be logged, approved by a human or rejected, and a chain of checks decides what actually runs. The patterns become the <strong>guardrails</strong> of a non-deterministic behavior.</p><h3>What’s Next</h3><p>Behavioral patterns have come a long way: from hand-written hierarchies to delegates, from iterator classes to yield return, from double dispatch to exhaustive switches. Many are now part of the language; others, like the Mediator, remain a design choice to be made with care. The key to success is the same as with the other families: <strong>use the language when it already solves the problem, and the pattern when it doesn&#39;t</strong>.</p><p>In the upcoming articles, we’ll explore each behavioral pattern individually, starting with the <a href="https://medium.com/p/bfc8ae80401f">Chain of Responsibility</a>.</p><p>Stay tuned.</p><p>Thanks for reading.</p><p>If you found this article helpful, follow me for the next ones or just clap.</p><p>Back to article <a href="https://medium.com/@emanuele.longo992/introduction-to-design-patterns-with-c-net-when-you-should-really-use-them-3dcb22be1c46">Introduction to Design Patterns with C# .NET</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5d6d72bc9f6b" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/behavioral-patterns-in-net-c-coordinating-objects-and-responsibilities-in-modern-applications-5d6d72bc9f6b">Behavioral Patterns in .NET C#: Coordinating objects and responsibilities in modern applications</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Extension Object Pattern in .NET C#: From GetExtension to feature collections (2026)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/extension-object-pattern-in-net-c-from-getextension-to-feature-collections-2026-4a6d2a7140ab?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*Q4_L-5kfSURKU9tc7VU4FQ.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine developing the order module of an e-commerce site. The Order class lives in the core of the system, and checkout, warehouse and&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/extension-object-pattern-in-net-c-from-getextension-to-feature-collections-2026-4a6d2a7140ab?source=rss-6cbbf07417e5------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/extension-object-pattern-in-net-c-from-getextension-to-feature-collections-2026-4a6d2a7140ab?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/4a6d2a7140ab</guid>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Mon, 02 Nov 2026 05:12:52 GMT</pubDate>
            <atom:updated>2026-11-02T17:44:33.756Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Nullable Reference Types and Null-Conditional Assignment in C# 14: From NullReferenceException to…]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/nullable-reference-types-and-null-conditional-assignment-in-c-14-from-nullreferenceexception-to-90a748b01e5c?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1200/1*du9PhlT_rVGNTx4frIkLkw.jpeg" width="1200"></a></p><p class="medium-feed-snippet">Null is one of the oldest companions of every C# developer. If you&#x2019;ve ever written C# code, you&#x2019;ve met it, usually in a stack trace and at&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/nullable-reference-types-and-null-conditional-assignment-in-c-14-from-nullreferenceexception-to-90a748b01e5c?source=rss-6cbbf07417e5------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/nullable-reference-types-and-null-conditional-assignment-in-c-14-from-nullreferenceexception-to-90a748b01e5c?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/90a748b01e5c</guid>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[dotnet]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Mon, 02 Nov 2026 05:12:19 GMT</pubDate>
            <atom:updated>2026-11-02T05:12:19.243Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Event Sourcing in .NET C#: From the accountant’s ledger to an event store (2026)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@emanuele.longo992/event-sourcing-in-net-c-from-the-accountants-ledger-to-an-event-store-2026-707bcef66f53?source=rss-6cbbf07417e5------2"><img src="https://cdn-images-1.medium.com/max/1400/1*QwX5xDYvGHvf1Dj7Z2uDCQ.jpeg" width="1400"></a></p><p class="medium-feed-snippet">Imagine your e-commerce is online, and support writes to you about one order. Why was the total 36 and not 40? When was the coupon applied&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@emanuele.longo992/event-sourcing-in-net-c-from-the-accountants-ledger-to-an-event-store-2026-707bcef66f53?source=rss-6cbbf07417e5------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@emanuele.longo992/event-sourcing-in-net-c-from-the-accountants-ledger-to-an-event-store-2026-707bcef66f53?source=rss-6cbbf07417e5------2</link>
            <guid isPermaLink="false">https://medium.com/p/707bcef66f53</guid>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[domain-driven-design]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Emanuele Longo]]></dc:creator>
            <pubDate>Sun, 01 Nov 2026 14:01:06 GMT</pubDate>
            <atom:updated>2026-11-02T17:57:33.055Z</atom:updated>
        </item>
    </channel>
</rss>