<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anton Grebenkin</title>
    <description>The latest articles on DEV Community by Anton Grebenkin (@antongrebenkin).</description>
    <link>https://dev.to/antongrebenkin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F630636%2Fbf0dfa8a-62f0-4357-8b49-fd2db91e47ea.jpg</url>
      <title>DEV Community: Anton Grebenkin</title>
      <link>https://dev.to/antongrebenkin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/antongrebenkin"/>
    <language>en</language>
    <item>
      <title>The Hidden Behavior of C# Records</title>
      <dc:creator>Anton Grebenkin</dc:creator>
      <pubDate>Tue, 05 Aug 2025 11:48:17 +0000</pubDate>
      <link>https://dev.to/antongrebenkin/the-hidden-behavior-of-c-records-59nc</link>
      <guid>https://dev.to/antongrebenkin/the-hidden-behavior-of-c-records-59nc</guid>
      <description>&lt;p&gt;C# records, introduced in C# 9, have become a favorite among developers for creating immutable data-transfer objects. Their concise syntax for defining properties, along with built-in value equality and a &lt;code&gt;ToString()&lt;/code&gt; override, simplifies a lot of boilerplate code. One of their most celebrated features is the &lt;code&gt;with&lt;/code&gt; expression, which allows for "nondestructive mutation"—creating a copy of a record with some properties changed.&lt;/p&gt;

&lt;p&gt;However, there's a subtle but critical behavior related to the &lt;code&gt;with&lt;/code&gt; expression that can easily catch developers by surprise: &lt;strong&gt;properties that are initialized from other primary constructor parameters are not recalculated when you create a copy using &lt;code&gt;with&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Seemingly Simple Scenario
&lt;/h4&gt;

&lt;p&gt;Let's consider a common use case: a &lt;code&gt;Person&lt;/code&gt; record that has a &lt;code&gt;FirstName&lt;/code&gt;, a &lt;code&gt;LastName&lt;/code&gt;, and a &lt;code&gt;FullName&lt;/code&gt; property derived from the other two. A developer might intuitively write it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This property is calculated ONCE during construction.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FullName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks perfectly reasonable. When we create a new &lt;code&gt;Person&lt;/code&gt;, the &lt;code&gt;FullName&lt;/code&gt; property is correctly initialized.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Outputs: FirstName: John, LastName: Doe, FullName: John Doe&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"FirstName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, LastName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, FullName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem arises when we use the &lt;code&gt;with&lt;/code&gt; expression to create a modified copy. What would you expect the &lt;code&gt;FullName&lt;/code&gt; to be in the following code?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;person2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Jane"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// What will this output?&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"FirstName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, LastName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, FullName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many developers would expect the output to be &lt;code&gt;FirstName: Jane, LastName: Doe, FullName: Jane Doe&lt;/code&gt;. After all, we changed the &lt;code&gt;FirstName&lt;/code&gt;, so the &lt;code&gt;FullName&lt;/code&gt; should update accordingly.&lt;/p&gt;

&lt;p&gt;The actual output is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FirstName: Jane, LastName: Doe, FullName: John Doe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;FullName&lt;/code&gt; was not recalculated. It retained the value from the original &lt;code&gt;person1&lt;/code&gt; object.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Does This Happen? The Mechanics of &lt;code&gt;with&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The root cause lies in how the &lt;code&gt;with&lt;/code&gt; expression is implemented by the C# compiler. Under the hood, a &lt;code&gt;with&lt;/code&gt; expression is syntactic sugar for a method call that performs a &lt;strong&gt;shallow, member-wise copy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you define a record, the compiler generates a hidden copy constructor. This constructor is what the &lt;code&gt;with&lt;/code&gt; expression uses as its foundation. Conceptually, it looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is a simplified, conceptual representation of what the compiler generates&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- The crucial line&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight is that the copy constructor copies the values from the &lt;em&gt;backing fields&lt;/em&gt; of the original object. In our example, &lt;code&gt;person1&lt;/code&gt; had its &lt;code&gt;FullName&lt;/code&gt; backing field initialized to "John Doe". The copy constructor simply copied that string value over to the new instance. It &lt;strong&gt;does not re-execute the property initializer&lt;/strong&gt; (&lt;code&gt;= $"{FirstName} {LastName}"&lt;/code&gt;). The property initializer is only executed when the primary constructor is called directly, not when the copy constructor is used.&lt;/p&gt;

&lt;p&gt;After the shallow copy is complete, the &lt;code&gt;with&lt;/code&gt; expression then assigns the new value for &lt;code&gt;FirstName&lt;/code&gt;, but by then it's too late for &lt;code&gt;FullName&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Solution: Use a True Computed Property
&lt;/h4&gt;

&lt;p&gt;To achieve the expected behavior where a derived property is always up-to-date, you must define it as a true computed property using an expression-bodied member (often called a "fat arrow" property).&lt;/p&gt;

&lt;p&gt;Here is the corrected version of the &lt;code&gt;Person&lt;/code&gt; record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This is a computed property. It is re-evaluated on every access.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FullName&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key difference is the use of &lt;code&gt;=&amp;gt;&lt;/code&gt; instead of &lt;code&gt;{ get; } =&lt;/code&gt;. An expression-bodied property does not have a backing field. Instead, it is essentially a method that is executed every single time the property is accessed.&lt;/p&gt;

&lt;p&gt;Now, if we run the same test code with this new record definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;person2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Jane"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Now, this produces the expected result&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"FirstName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, LastName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, FullName: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will be correct:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FirstName: Jane, LastName: Doe, FullName: Jane Doe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This works because when we access &lt;code&gt;person2.FullName&lt;/code&gt;, the code &lt;code&gt;$"{FirstName} {LastName}"&lt;/code&gt; is executed in the context of &lt;code&gt;person2&lt;/code&gt;, using its current property values.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;with&lt;/code&gt; expression is a powerful tool for working with immutable data, but it's vital to understand its mechanics. Remember this key distinction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Property with an initializer&lt;/strong&gt; (&lt;code&gt;public string Prop { get; } = ...&lt;/code&gt;): The value is calculated &lt;strong&gt;once&lt;/strong&gt; during initial construction and is copied as-is by the &lt;code&gt;with&lt;/code&gt; expression.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Computed property&lt;/strong&gt; (&lt;code&gt;public string Prop =&amp;gt; ...&lt;/code&gt;): The value is calculated &lt;strong&gt;on every access&lt;/strong&gt; and will always reflect the current state of the object, making it the correct choice for derived values that must stay in sync.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>csharp</category>
    </item>
    <item>
      <title>FlashEvents: A Free, Simple Alternative to MediatR Notification Publisher</title>
      <dc:creator>Anton Grebenkin</dc:creator>
      <pubDate>Mon, 14 Jul 2025 10:49:10 +0000</pubDate>
      <link>https://dev.to/antongrebenkin/flashevents-a-free-simple-alternative-to-mediatr-notification-publisher-5dla</link>
      <guid>https://dev.to/antongrebenkin/flashevents-a-free-simple-alternative-to-mediatr-notification-publisher-5dla</guid>
      <description>&lt;h2&gt;
  
  
  The Situation
&lt;/h2&gt;

&lt;p&gt;Let's be honest, many of us in the .NET world have relied on MediatR. It's a fantastic library that has shaped how we think about CQRS and in-process messaging. However, with the recent introduction of a licensing model, many developers are looking for free, open-source alternatives for its notification (publish/subscribe) capabilities.&lt;/p&gt;

&lt;p&gt;I was in the same boat. I love the pub/sub pattern for decoupling components, but I needed a solution that was not only free but also incredibly fast and architecturally sound, especially for applications using services with specific lifetimes, like Entity Framework's &lt;code&gt;DbContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's why I created &lt;strong&gt;FlashEvents&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Anton-Grebenkin/FlashEvents" rel="noopener noreferrer"&gt;FlashEvents&lt;/a&gt; is a high-performance, in-memory event publishing library for .NET designed with two core principles in mind: &lt;strong&gt;simplicity and speed&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes FlashEvents Different?
&lt;/h2&gt;

&lt;p&gt;FlashEvents focuses exclusively on the "notification" or "event publishing" part of the pattern. Its key features are designed to solve common problems gracefully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  🚀 &lt;strong&gt;Blazing Fast Performance&lt;/strong&gt;: It's optimized for low-latency and minimal memory allocations. (We'll get to the benchmarks later!)&lt;/li&gt;
&lt;li&gt;  ⚡ &lt;strong&gt;Parallel Execution by Default&lt;/strong&gt;: When you publish an event, all its handlers run concurrently using &lt;code&gt;Task.WhenAll&lt;/code&gt;. This maximizes throughput without any special configuration.&lt;/li&gt;
&lt;li&gt;  🛡️ &lt;strong&gt;Scoped Handler Isolation&lt;/strong&gt;: This is the killer feature. &lt;strong&gt;Each event handler is resolved and executed in its own &lt;code&gt;IServiceScope&lt;/code&gt;&lt;/strong&gt;. This completely prevents issues with shared state. If one handler uses a &lt;code&gt;DbContext&lt;/code&gt;, it gets its own instance. Another handler can use its own &lt;code&gt;DbContext&lt;/code&gt; or other scoped services without any conflicts. This is a huge win for reliability.&lt;/li&gt;
&lt;li&gt;  🔧 &lt;strong&gt;Simple &amp;amp; Fluent API&lt;/strong&gt;: Setting it up is a breeze with clean dependency injection extensions.&lt;/li&gt;
&lt;li&gt;  🔍 &lt;strong&gt;Automatic Handler Discovery&lt;/strong&gt;: A single line of code can register all your event handlers from an assembly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's See It in Action
&lt;/h2&gt;

&lt;p&gt;Here’s how you can integrate FlashEvents into your project in just a few minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Define Your Event
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;FlashEvents.Abstractions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;OrderCreatedEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;OrderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;CustomerEmail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create Event Handlers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;FlashEvents.Abstractions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Handler 1: Sends a welcome email&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendWelcomeEmailHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IEventHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderCreatedEvent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IEmailService&lt;/span&gt; &lt;span class="n"&gt;_emailService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Can be transient or singleton&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;SendWelcomeEmailHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEmailService&lt;/span&gt; &lt;span class="n"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderCreatedEvent&lt;/span&gt; &lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... send email ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Handler 2: Updates analytics using a scoped service&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdateAnalyticsHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IEventHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OrderCreatedEvent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IAnalyticsService&lt;/span&gt; &lt;span class="n"&gt;_analyticsService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Scoped service&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UpdateAnalyticsHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IAnalyticsService&lt;/span&gt; &lt;span class="n"&gt;analyticsService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderCreatedEvent&lt;/span&gt; &lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... update analytics ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Configure Dependency Injection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;FlashEvents&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Reflection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Add FlashEvents services&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEventPublisher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Automatically discover and register all handlers&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEventHandlersFromAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetExecutingAssembly&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Register your other application services&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTransient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEmailService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EmailService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IanalyticsService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AnalyticsService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Our scoped service&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Publish an Event
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;FlashEvents.Abstractions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[controller]"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrdersController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IEventPublisher&lt;/span&gt; &lt;span class="n"&gt;_eventPublisher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrdersController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IEventPublisher&lt;/span&gt; &lt;span class="n"&gt;eventPublisher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_eventPublisher&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eventPublisher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HttpPost&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... logic to create an order ...&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;orderEvent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OrderCreatedEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"test@example.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Publish it. FlashEvents handles the rest.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_eventPublisher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PublishAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Order created and events are being handled."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  But Is It Fast? The Benchmarks
&lt;/h2&gt;

&lt;p&gt;Talk is cheap. Let's look at the numbers against MediatR v12.5.0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System:&lt;/strong&gt; i5-13400F, .NET 8&lt;/p&gt;




&lt;h3&gt;
  
  
  Scenario 1: Single Handler (vs. MediatR's Parallel Publisher)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;StdDev&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;Allocated&lt;/th&gt;
&lt;th&gt;Alloc Ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FlashEvents_Publish&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;205.1 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.79 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.68 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;520 B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MediatR_Publish&lt;/td&gt;
&lt;td&gt;141.19 ns&lt;/td&gt;
&lt;td&gt;1.114 ns&lt;/td&gt;
&lt;td&gt;0.988 ns&lt;/td&gt;
&lt;td&gt;1.55&lt;/td&gt;
&lt;td&gt;664 B&lt;/td&gt;
&lt;td&gt;3.77&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Scenario 2: Two Handlers (vs. MediatR's Parallel Publisher)
&lt;/h3&gt;

&lt;p&gt;This test highlights the parallel execution for two handlers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;StdDev&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;Allocated&lt;/th&gt;
&lt;th&gt;Alloc Ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FlashEvents_Publish&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;269.3 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.34 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.79 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;712 B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MediatR_Publish&lt;/td&gt;
&lt;td&gt;171.4 ns&lt;/td&gt;
&lt;td&gt;0.95 ns&lt;/td&gt;
&lt;td&gt;0.79 ns&lt;/td&gt;
&lt;td&gt;0.64&lt;/td&gt;
&lt;td&gt;824 B&lt;/td&gt;
&lt;td&gt;1.16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Choose FlashEvents?
&lt;/h2&gt;

&lt;p&gt;If you need the request/response or pipeline behaviors from MediatR, then MediatR is still the tool for the job.&lt;/p&gt;

&lt;p&gt;But if you are primarily using its &lt;strong&gt;notification publisher&lt;/strong&gt; feature, FlashEvents offers a compelling alternative:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Free &amp;amp; Open Source:&lt;/strong&gt; It's licensed under MIT. No fees, no strings attached.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Architectural Safety:&lt;/strong&gt; Built-in scoped execution for handlers is a huge advantage that prevents a common class of bugs related to dependency lifetimes.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Simplicity:&lt;/strong&gt; It does one thing and does it well. The API surface is minimal and easy to learn.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Performance:&lt;/strong&gt; It's extremely lightweight and holds its own against the industry standard, especially regarding memory allocations.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Give It a Try!
&lt;/h2&gt;

&lt;p&gt;I built FlashEvents to solve a problem I was facing, and I hope it can help you too. It's available on NuGet, and the source code is on GitHub.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;NuGet Package:&lt;/strong&gt; &lt;a href="https://www.nuget.org/packages/FlashEvents/" rel="noopener noreferrer"&gt;&lt;code&gt;FlashEvents&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/Anton-Grebenkin/FlashEvents" rel="noopener noreferrer"&gt;&lt;code&gt;Anton-Grebenkin/FlashEvents&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>pubsub</category>
      <category>dotnet</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
