<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom">
  <channel>
    <title>Metalama Blog</title>
    <description>Patterns and architecture tooling for C#: PostSharp and Metalama.</description>
    <link>https://postsharp.net</link>
    <atom:link href="https://postsharp.net/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 06 Aug 2026 07:47:18 +0000</pubDate>
    <lastBuildDate>Thu, 06 Aug 2026 07:47:18 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Security and Privacy Update for PostSharp and Metalama</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2026/2026-06-security/metalama.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;Today we are shipping a coordinated security and privacy update across every supported branch of PostSharp and Metalama. It covers the build toolchain, the design time services, telemetry, and the Visual Studio Tools. It does not change the public API or how you write aspects, and none of it reaches your compiled application: every issue is in tooling that runs on developer and build machines, so the applications you have already built and shipped are not affected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short:&lt;/strong&gt; All fixes are already shipped on every supported branch. The most serious issues (three High-severity advisories) require an attacker to already have a local account on your machine, so they mainly affect shared or multi-user build agents. Upgrade when convenient; prioritize it if you build on shared agents. Nothing else to do.&lt;/p&gt;

&lt;h2 id=&quot;scope-and-attack-vectors&quot;&gt;Scope and attack vectors&lt;/h2&gt;

&lt;p&gt;We published GitHub Security Advisories for the most severe findings, all rated High. They require the attacker to already have local access to the same machine, under a different user account, which mainly matters on shared or multi-user build agents.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;PostSharp&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;Local code execution, information disclosure, and denial of service in the build toolchain on shared machines (&lt;a href=&quot;https://github.com/postsharp/PostSharp.Public/security/advisories/GHSA-gpwg-4q4j-792q&quot;&gt;GHSA-gpwg-4q4j-792q&lt;/a&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Metalama&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;Unsafe deserialization over the Visual Studio named pipe enables local code execution (&lt;a href=&quot;https://github.com/metalama/Metalama/security/advisories/GHSA-h26j-4vp7-x9w2&quot;&gt;GHSA-h26j-4vp7-x9w2&lt;/a&gt;)&lt;/li&gt;
      &lt;li&gt;Local code execution via DLL planting in world-writable temp directories on Linux/macOS (&lt;a href=&quot;https://github.com/metalama/Metalama/security/advisories/GHSA-m6wq-39m7-9xpp&quot;&gt;GHSA-m6wq-39m7-9xpp&lt;/a&gt;)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We found and fixed other vulnerabilities that required the attacker to sit between your device and our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;postsharp.net&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metalama.net&lt;/code&gt; servers as a man-in-the-middle. See the GitHub release notes in the &lt;em&gt;What changed&lt;/em&gt; section below.&lt;/p&gt;

&lt;p&gt;None of these vulnerabilities could be exploited by a remote attacker against a normal developer or CI setup.&lt;/p&gt;

&lt;p&gt;One assumption is unchanged: like the .NET SDK itself, PostSharp and Metalama assume your source code and NuGet dependencies are trusted, and they execute that code at build time. This review hardened everything around that boundary, but it does not sandbox hostile source or malicious packages. Vetting what enters your build remains your job.&lt;/p&gt;

&lt;p&gt;There is no known exploitation, and no customer needs to do anything beyond upgrading when convenient.&lt;/p&gt;

&lt;h2 id=&quot;why-now-and-not-sooner&quot;&gt;Why now, and not sooner&lt;/h2&gt;

&lt;p&gt;No attacker or customer reported these issues. We found and disclosed them ourselves, and published the advisories with the fixes already shipped on every supported branch.&lt;/p&gt;

&lt;p&gt;Why now? Because the new generation of AI models makes it both possible and urgent. Auditing a 20-year-old living codebase used to mean weeks of work and skills we didn’t have in-house. It did not seem necessary for a niche tool that processes trusted local inputs without network access. However, with new AI tools, an in-depth security analysis takes a couple of hours, both for the publisher and the attacker. We used Claude Opus 4.8 for the review, reviewed every finding, supervised and refined the fixes, and tested them on real VMs before release. The whole pass still took weeks; without the model it would not have happened.&lt;/p&gt;

&lt;h2 id=&quot;run-the-analysis-yourself&quot;&gt;Run the analysis yourself&lt;/h2&gt;

&lt;p&gt;We believe that security stems from transparency. Ultimately, it does not matter &lt;em&gt;who&lt;/em&gt; wrote the code you execute. What matters is the code itself.&lt;/p&gt;

&lt;p&gt;Metalama is open source: clone it from &lt;a href=&quot;https://github.com/metalama/Metalama&quot;&gt;GitHub&lt;/a&gt; and point your own tools at it. PostSharp’s source is available to enterprise customers at no additional charge under a source-available license, going back to version 1.0; see &lt;a href=&quot;/blog/postsharp-source-available&quot;&gt;PostSharp Is Now Source Available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you run your own analysis, report any defects privately through GitHub Security Advisories (&lt;a href=&quot;https://github.com/metalama/Metalama/security/advisories&quot;&gt;Metalama&lt;/a&gt;, &lt;a href=&quot;https://github.com/postsharp/PostSharp.Public/security/advisories&quot;&gt;PostSharp&lt;/a&gt;) and we will handle them the way we handled this review. Our &lt;a href=&quot;https://www.postsharp.net/compliance/security&quot;&gt;security policy&lt;/a&gt; describes how we receive, prioritize, and disclose vulnerabilities.&lt;/p&gt;

&lt;h2 id=&quot;what-changed&quot;&gt;What changed&lt;/h2&gt;

&lt;p&gt;Across all these releases, the work falls into a few themes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Safer behavior on shared machines.&lt;/strong&gt; Caches, temp files, and local servers now stay scoped to the current user, so one user cannot interfere with or read another’s build.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Telemetry hardened to minimize what leaves your machine.&lt;/strong&gt; Crash reports now omit exception messages and data, and do a more thorough job scrubbing both secrets and confidential identifiers, such as a company name embedded in a namespace, so a stack trace can’t carry a token, a connection string, or your internal names off your machine. We rotate device IDs monthly and keep separate salts for our own diagnostics and our third-party analytics, so the two are much harder to correlate. For exactly what we collect and how to turn it off, see our &lt;a href=&quot;https://www.postsharp.net/company/legal/privacy-policy&quot;&gt;privacy policy&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Removed features that collected data.&lt;/strong&gt; We took out the in-product extras that came with a data cost: the Learning Hub tool window in Visual Studio, the Areas of Interest selection, and newsletter and email registration. We also removed the telemetry code for the long-defunct per-usage licensing model, which used to upload reversibly-hashed type names.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Defense in depth against our own servers.&lt;/strong&gt; Some data comes from postsharp.net or metalama.net, such as the news feed and content feeds. We hardened the parsers and serializers that handle it, so a compromise of our servers could not turn that data into code execution on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The LTS and latest branches get the full set of changes. The two Metalama advisory fixes were also backported to the other supported versions, 2025.1.18 and 2026.0.25, without the broader privacy and telemetry rework. See the &lt;a href=&quot;https://www.postsharp.net/support/policies/versions&quot;&gt;version status page&lt;/a&gt; for what is still serviced.&lt;/p&gt;

&lt;p&gt;The per-release notes have the full technical detail:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;PostSharp&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/postsharp/PostSharp.Public/releases/tag/v2026.0.13&quot;&gt;2026.0.13&lt;/a&gt; (Current)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/postsharp/PostSharp.Public/releases/tag/v2024.0.23&quot;&gt;2024.0.23&lt;/a&gt; (LTS)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Metalama&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release/2026.1.19&quot;&gt;2026.1.19&lt;/a&gt; (Current)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release/2026.0.25&quot;&gt;2026.0.25&lt;/a&gt; (Extended Support: advisory fixes only)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release/2025.1.18&quot;&gt;2025.1.18&lt;/a&gt; (Extended Support: advisory fixes only)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Visual Studio Tools for PostSharp and Metalama&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama.Vsx.Public/releases/tag/release/2026.1.5&quot;&gt;2026.1.5&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All packages are on &lt;a href=&quot;https://www.nuget.org/packages/Metalama.Framework&quot;&gt;NuGet.org&lt;/a&gt;, and the extension is on the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=PostSharpTechnologies.PostSharp&quot;&gt;Visual Studio Marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;updated-policies&quot;&gt;Updated policies&lt;/h2&gt;

&lt;p&gt;As part of this review we updated our &lt;a href=&quot;https://www.postsharp.net/company/legal/privacy-policy&quot;&gt;privacy policy&lt;/a&gt; to describe exactly what we collect, and our &lt;a href=&quot;https://www.postsharp.net/compliance/security&quot;&gt;security policy&lt;/a&gt; to reflect the current threat model and how to report a vulnerability.&lt;/p&gt;

&lt;h2 id=&quot;how-to-upgrade&quot;&gt;How to upgrade&lt;/h2&gt;

&lt;p&gt;For most users this is a drop-in upgrade: bump the NuGet versions and update the extension. No API changes, nothing to reconfigure. Open-source and free-edition users can upgrade freely; for commercial editions, upgrading requires an active maintenance subscription. If you build on shared or multi-user agents, prioritize it.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;The next Metalama and PostSharp feature releases will focus on .NET 11 support, with work starting in late August.&lt;/p&gt;

&lt;p&gt;Found an issue or have a feature request? Let us know on &lt;a href=&quot;https://github.com/metalama/Metalama/issues&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy meta-programming!&lt;/p&gt;

&lt;p&gt;-gael&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/security-privacy-hardening-2026-06"&gt;Security and Privacy Update for PostSharp and Metalama&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Tue, 30 Jun 2026 19:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/security-privacy-hardening-2026-06</link>
        <guid isPermaLink="true">https://postsharp.net/blog/security-privacy-hardening-2026-06</guid>
        
        <category>featured</category>
        
        
        <category>PostSharp</category>
        
        <category>Metalama</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2026/2026-06-security/metalama.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>Metalama 2026.1 Generally Available: First LTS Release, Complete C# 14 Support, and a Redesigned Redis Backend</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2026/2026-06-announcement/metalama.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;Metalama 2026.1 is now generally available, and it’s our first &lt;strong&gt;long-term support (LTS)&lt;/strong&gt; release. This is a consolidation release: we finished the C# 14 work we started in 2026.0, extended the advising API, redesigned the Redis caching backend, cut several third-party dependencies, and closed most of the bug backlog.&lt;/p&gt;

&lt;p&gt;The packages are on &lt;a href=&quot;https://www.nuget.org/packages/Metalama.Framework&quot;&gt;NuGet.org&lt;/a&gt;, and the Visual Studio extension is on the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=PostSharpTechnologies.PostSharp&quot;&gt;Visual Studio Marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the complete list of changes, see the &lt;a href=&quot;https://doc.metalama.net/conceptual/release-notes/release-notes-2026-1&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;complete-c-14-support-in-aspects&quot;&gt;Complete C# 14 support in aspects&lt;/h2&gt;

&lt;p&gt;In 2026.0 we supported all C# 14 features in your own code but left a few gaps in aspects. Those gaps are now closed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Introducing extension blocks.&lt;/strong&gt; The new &lt;a href=&quot;https://doc.metalama.net/api/metalama-framework-aspects-adviserextensions-introduceextensionblock&quot;&gt;IntroduceExtensionBlock&lt;/a&gt; advice lets aspects add extension blocks to static classes. See &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/advising/introducing-types&quot;&gt;Introducing types&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Contracts on extension-block receiver parameters.&lt;/strong&gt; You can now add a contract to the receiver parameter of an extension block, and it propagates across the extension members.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Introducing user-defined compound assignment operators.&lt;/strong&gt; Operators such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-=&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*=&lt;/code&gt; can now be introduced through &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/advising/introducing-members&quot;&gt;IntroduceMethod&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Run-time invoker interfaces for extension members.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Introducing parameters into partial constructors.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two C# 14 constructs remain unsupported &lt;em&gt;inside templates&lt;/em&gt;: null-conditional assignments (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x?.P = v&lt;/code&gt;) and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field&lt;/code&gt; keyword. Rather than fail confusingly, Metalama now detects them and reports a clear diagnostic (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LAMA0101&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;initialization-advice&quot;&gt;Initialization advice&lt;/h2&gt;

&lt;p&gt;We’ve extended the &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/advising/initializers&quot;&gt;initialization advice&lt;/a&gt; with two new initializer kinds and better support for records:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterLastInstanceConstructor&lt;/code&gt;&lt;/strong&gt; injects code into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected virtual OnConstructed&lt;/code&gt; method, so it runs once after the most-derived constructor completes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AfterObjectInitializer&lt;/code&gt;&lt;/strong&gt; runs after the constructor and any object initializer or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; expression have completed. Metalama makes the target implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IInitializable&lt;/code&gt; and rewrites the call sites accordingly, so you can validate or compute derived state once every property has been set.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BeforeInstanceConstructor&lt;/code&gt;&lt;/strong&gt; now works on positional records with primary constructors.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/advising/introducing-constructor-parameters&quot;&gt;Constructor parameter introduction&lt;/a&gt;&lt;/strong&gt; can now generate forwarding overloads, so you can add a parameter without breaking binary compatibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;dependency-injection&quot;&gt;Dependency injection&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://doc.metalama.net/api/metalama-framework-advising-pullstrategy-introduceparameterandpull&quot;&gt;IntroduceParameterAndPull&lt;/a&gt; now accepts a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reuseExistingParameterOfCompatibleType&lt;/code&gt; argument. When a chained constructor already accepts a parameter of the same or a more specific type, the existing parameter is forwarded instead of duplicated. The default .NET DI adapter relies on this: an aspect that pulls an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILogger&amp;lt;T&amp;gt;&lt;/code&gt; no longer adds a second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILogger&amp;lt;T&amp;gt;&lt;/code&gt; parameter when the target constructor already has one. See &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/dependency-injection&quot;&gt;Injecting dependencies into aspects&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;redesigned-redis-caching-backend&quot;&gt;Redesigned Redis caching backend&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://doc.metalama.net/patterns/caching/redis&quot;&gt;Metalama.Patterns.Caching.Backends.Redis&lt;/a&gt; received a major overhaul, porting the work we did for PostSharp 2025.1 (see &lt;a href=&quot;/blog/redis-caching-update&quot;&gt;Breaking Update of PostSharp Caching adapter for Redis in 2025.1&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;New data schema.&lt;/strong&gt; Reading a cache item is now a single, observationally-consistent operation, and cache keys are versioned.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cluster support.&lt;/strong&gt; Hash tags keep related keys on the same shard, and you can configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadCommandFlags&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteCommandFlags&lt;/code&gt; for multi-node setups.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Retry and exception-handling policies.&lt;/strong&gt; The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IRetryPolicy&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IExceptionHandlingPolicy&lt;/code&gt; interfaces give you exponential backoff and centralized error handling.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Key compression.&lt;/strong&gt; Keys longer than a configurable threshold (128 characters by default) are hashed automatically with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XxHash64&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XxHash128&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Overload detection.&lt;/strong&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IsBackgroundTaskQueueOverloaded&lt;/code&gt; property lets you back off under pressure, and the dependency garbage collector pauses itself when the queue is saturated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you use the Redis backend, note that the schema change requires purging the cache (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FLUSHDB&lt;/code&gt;) on upgrade. See the breaking changes below.&lt;/p&gt;

&lt;h2 id=&quot;fewer-third-party-dependencies&quot;&gt;Fewer third-party dependencies&lt;/h2&gt;

&lt;p&gt;We reduced our dependency surface to improve supply-chain safety:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Text.Json&lt;/code&gt; replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Newtonsoft.Json&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.IO.Hashing&lt;/code&gt; replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;K4os.Hash&lt;/code&gt; (the xxHash implementation now comes from the .NET runtime).&lt;/li&gt;
  &lt;li&gt;Diff-tool integration moved to the optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Metalama.Extensions.DiffEngine&lt;/code&gt; package, and HTML test output moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Metalama.Extensions.HtmlWriter&lt;/code&gt; (both used in &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/testing/snapshot-testing&quot;&gt;aspect snapshot testing&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;We no longer use MD5 for non-cryptographic hashing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;performance-improvements&quot;&gt;Performance improvements&lt;/h2&gt;

&lt;p&gt;This release improves both build-time and design-time performance. At build time, configuration files now use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Text.Json&lt;/code&gt; source generators, polymorphic pattern matching in the code model was restructured to match on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DeclarationKind&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeKind&lt;/code&gt;, and the WPF temporary compilation phase (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MarkupCompilePass1&lt;/code&gt;) runs a reduced pipeline that emits member signatures only and skips the linker step. At design time, the protocol between the analyzer and the design-time services moved from JSON to MessagePack.&lt;/p&gt;

&lt;h2 id=&quot;bug-fixes&quot;&gt;Bug fixes&lt;/h2&gt;

&lt;p&gt;We fixed over 100 bugs in this release, spanning the template engine, linker, code model, design-time services, dependency injection, and diagnostics. Metalama 2026.1 is the first release ever to ship with (almost) zero known bugs.&lt;/p&gt;

&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h2&gt;

&lt;p&gt;A few changes may affect existing code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddInitializer&lt;/code&gt; ordering now respects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AspectOrderDirection.RunTime&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IntroduceParameter&lt;/code&gt; on a record primary constructor no longer materializes the parameter by default; opt in with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;materializeOnRecord&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IConstructor.InitializerKind&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base&lt;/code&gt; (instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;) for an implicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base()&lt;/code&gt; call.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IEvent.RaiseMethod&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; for non-raisable events. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IEventInvoker.CanRaise&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The test base classes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AspectTestClass&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAspectTestClass&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CurrentDirectoryAttribute&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CurrentProjectAttribute&lt;/code&gt; were removed.&lt;/li&gt;
  &lt;li&gt;For the Redis backend: the schema redesign requires a cache purge, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExceptionHandlingCachingBackendEnhancer&lt;/code&gt; was removed in favor of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExceptionHandlingPolicy&lt;/code&gt; property, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransactionMaxRetries&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CacheCleanupOptions.Sequential&lt;/code&gt; are obsolete.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href=&quot;https://doc.metalama.net/conceptual/release-notes/release-notes-2026-1#breaking-changes&quot;&gt;release notes&lt;/a&gt; for the full list.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;As our first LTS release, 2026.1 is the version to standardize on if you want stability. The next feature release is expected to be 2027.0, with support for .NET 11. Work will start in late August, and we don’t expect any larger work on Metalama in the meantime.&lt;/p&gt;

&lt;p&gt;Found an issue or have a feature request? Let us know on &lt;a href=&quot;https://github.com/metalama/Metalama/issues&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy meta-programming!&lt;/p&gt;

&lt;p&gt;-gael&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/metalama-2026-1-ga"&gt;Metalama 2026.1 Generally Available: First LTS Release, Complete C# 14 Support, and a Redesigned Redis Backend&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Wed, 03 Jun 2026 07:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/metalama-2026-1-ga</link>
        <guid isPermaLink="true">https://postsharp.net/blog/metalama-2026-1-ga</guid>
        
        <category>featured</category>
        
        
        <category>Metalama</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2026/2026-06-announcement/metalama.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>PostSharp 2026.0 Generally Available: Support for .NET 10, C# 14 and Extension Blocks</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2026/2026-01-announcement/postsharp.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;Alongside &lt;a href=&quot;/blog/metalama-2026-0-ga&quot;&gt;Metalama 2026.0&lt;/a&gt;, we’re announcing the general availability of PostSharp 2026.0. This release brings full support for .NET 10 and C# 14, including proper handling of the new extension blocks syntax introduced in C# 14.&lt;/p&gt;

&lt;h2 id=&quot;net-10-and-c-14&quot;&gt;.NET 10 and C# 14&lt;/h2&gt;

&lt;p&gt;We’ve updated and tested PostSharp to fully support the .NET 10 SDK and C# 14 across all packages. You can now confidently use PostSharp with the latest .NET stack.&lt;/p&gt;

&lt;h2 id=&quot;extension-blocks-support&quot;&gt;Extension Blocks Support&lt;/h2&gt;

&lt;p&gt;C# 14 introduces extension blocks as an alternative syntax for defining extension methods. This new language feature required careful consideration in PostSharp to ensure predictable behavior.&lt;/p&gt;

&lt;p&gt;By default, multicast attributes now skip extension block members. This prevents aspects from being unintentionally applied to compiler-generated metadata associated with extension blocks.&lt;/p&gt;

&lt;p&gt;For scenarios where you do want to target extension block members, we’ve added the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AllowExtensionBlockMembers&lt;/code&gt; property to both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MulticastAttribute&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MulticastAttributeUsageAttribute&lt;/code&gt;. Setting this property to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; enables your aspects to target extension block members explicitly.&lt;/p&gt;

&lt;p&gt;Additionally, developers using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAspectProvider&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAdviceProvider&lt;/code&gt; interfaces can use the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReflectionHelper.IsExtensionBlockMetadata&lt;/code&gt; utility method to identify compiler-generated metadata associated with extension blocks.&lt;/p&gt;

&lt;h2 id=&quot;updated-framework-baselines&quot;&gt;Updated Framework Baselines&lt;/h2&gt;

&lt;p&gt;We’ve raised the minimum supported frameworks to reflect the current .NET ecosystem:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;.NET Standard 2.0&lt;/strong&gt; (minimum)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;.NET Framework 4.7.0&lt;/strong&gt; (minimum)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;.NET 6.0&lt;/strong&gt; (minimum for .NET Core-based projects)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All pre-2017 target frameworks and obsolete .NET Core versions that have lost mainstream support have been removed. Please consult the &lt;a href=&quot;https://doc.postsharp.net/introduction/whatsnew/whats-new-20260&quot;&gt;breaking changes documentation&lt;/a&gt; for complete migration guidance.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;PostSharp 2026.0 continues our commitment to keeping PostSharp compatible with the latest .NET releases. While our new feature development is focused on &lt;a href=&quot;/blog/metalama-2026-0-ga&quot;&gt;Metalama&lt;/a&gt;, we remain dedicated to ensuring that PostSharp users can stay current with the evolving .NET platform.&lt;/p&gt;

&lt;p&gt;Happy meta-programming with PostSharp!&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/postsharp-2026-0-ga"&gt;PostSharp 2026.0 Generally Available: Support for .NET 10, C# 14 and Extension Blocks&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Wed, 07 Jan 2026 07:00:00 +0000</pubDate>
        
        <link>https://postsharp.net/blog/postsharp-2026-0-ga</link>
        <guid isPermaLink="true">https://postsharp.net/blog/postsharp-2026-0-ga</guid>
        
        
        <category>PostSharp</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2026/2026-01-announcement/postsharp.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>Metalama 2026.0 Generally Available: Full Support for C# 14 and .NET 10</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2026/2026-01-announcement/metalama.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;Metalama 2026.0 is now generally available! This major release brings full support for C# 14 (the most significant evolution of the C# language in years), along with .NET 10 SDK and Visual Studio 2026 compatibility. We’re also closing one of the last feature gaps with PostSharp: the ability to override event handler invocations. And you’re getting first-class support for tuple types.&lt;/p&gt;

&lt;p&gt;Ready to try it? The packages are on &lt;a href=&quot;https://www.nuget.org/packages/Metalama.Framework&quot;&gt;NuGet.org&lt;/a&gt;, and the Visual Studio extension is available from the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=PostSharpTechnologies.PostSharp&quot;&gt;Visual Studio Marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the complete list of changes, see the &lt;a href=&quot;https://doc.metalama.net/conceptual/release-notes/release-notes-2026-0&quot;&gt;release notes&lt;/a&gt;. For even more detail, see the change notes for the releases &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.11&quot;&gt;2026.0.11&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.10-rc&quot;&gt;2026.0.10-rc&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.9-rc&quot;&gt;2026.0.9-rc&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.8-rc&quot;&gt;2026.0.8-rc&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.7-rc&quot;&gt;2026.0.7-rc&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.6-rc&quot;&gt;2026.0.6-rc&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.5-preview&quot;&gt;2026.0.5-preview&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.4-preview&quot;&gt;2026.0.4-preview&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.3-preview&quot;&gt;2026.0.3-preview&lt;/a&gt;, &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.2-preview&quot;&gt;2026.0.2-preview&lt;/a&gt;,
  &lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.1-preview&quot;&gt;2026.0.1-preview&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;c-14-support&quot;&gt;C# 14 support&lt;/h2&gt;

&lt;p&gt;C# 14 introduces several language features, and Metalama 2026.0 supports all of them &lt;em&gt;in user code&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Extension blocks (see below)&lt;/li&gt;
  &lt;li&gt;Null-conditional assignments&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field&lt;/code&gt; keyword in properties&lt;/li&gt;
  &lt;li&gt;Partial constructors and events&lt;/li&gt;
  &lt;li&gt;Compound assignment operators&lt;/li&gt;
  &lt;li&gt;Simple lambda parameters with modifiers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, some features are &lt;strong&gt;not yet supported in aspects&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Null-conditional assignments in templates&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field&lt;/code&gt; keyword in templates&lt;/li&gt;
  &lt;li&gt;Generating run-time code for extension members via invoker interfaces&lt;/li&gt;
  &lt;li&gt;Adding contracts to the receiver parameter of extension blocks&lt;/li&gt;
  &lt;li&gt;Introducing new compound assignment operators&lt;/li&gt;
  &lt;li&gt;Introducing parameters into partial constructors&lt;/li&gt;
  &lt;li&gt;Introducing new extension blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;extension-blocks&quot;&gt;Extension blocks&lt;/h2&gt;

&lt;p&gt;Extension blocks are the headline feature of C# 14, letting you extend any type with new members. Metalama supports them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Extension blocks are modeled via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IExtensionBlock&lt;/code&gt; interface, which implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeKind = Extension&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;They appear under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.ExtensionBlocks&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;You can override extension members using the advising API or apply aspects via custom attributes.&lt;/li&gt;
  &lt;li&gt;You can introduce new members into existing extension blocks.&lt;/li&gt;
  &lt;li&gt;Introducing &lt;em&gt;new&lt;/em&gt; extension blocks is not yet supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how to add logging to all extension methods in your project using a fabric:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Fabric&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProjectFabric&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AmendProject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IProjectAmender&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amender&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;amender&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SelectTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SelectMany&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ExtensionBlocks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SelectMany&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Methods&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AddAspectIfEligible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LogAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;event-handler-overriding&quot;&gt;Event handler overriding&lt;/h2&gt;

&lt;p&gt;You can now override event handler invocations, enabling patterns like “safe events” where each handler is isolated by exception handling. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OverrideInvoke&lt;/code&gt; method in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OverrideEventAspect&lt;/code&gt; intercepts individual handler invocations.&lt;/p&gt;

&lt;p&gt;Typical use cases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Safe events (exception isolation)&lt;/li&gt;
  &lt;li&gt;Background or asynchronous event dispatch&lt;/li&gt;
  &lt;li&gt;Event invocation logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an aspect that catches exceptions and removes faulty handlers:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SafeEventAttribute&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OverrideEventAspect&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OverrideInvoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Proceed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apply it to any event:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Camera&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SafeEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnFocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For details, see &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/advising/overriding-events&quot;&gt;Overriding events&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;first-class-tuple-support&quot;&gt;First-class tuple support&lt;/h2&gt;

&lt;p&gt;Previously, Metalama treated tuples as plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType&lt;/code&gt; objects, with no access to element names or types. The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITupleType&lt;/code&gt; interface changes that, making scenarios like packing method arguments for interceptors much cleaner:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Create a tuple type from method parameters.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TypeFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateTupleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Parameters&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create a tuple instance.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleExpression&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateCreateInstanceExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Parameters&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Pass it to an observer.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;_myObserver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OnMethodCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DeclaringType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;metrics-enhancements&quot;&gt;Metrics enhancements&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;LinesOfCode metric&lt;/strong&gt;: Three measurements (Logical, NonBlank, and Total).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Workspaces API&lt;/strong&gt;: Now officially supports metrics consumption.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;visual-studio-tooling-improvements&quot;&gt;Visual Studio tooling improvements&lt;/h2&gt;

&lt;p&gt;We’ve refactored several background components of our VSIX. It’s now more stable, consumes less CPU, and better utilizes your cores.&lt;/p&gt;

&lt;h2 id=&quot;claude-code-skill-for-ai-assisted-development&quot;&gt;Claude Code skill for AI-assisted development&lt;/h2&gt;

&lt;p&gt;We’re introducing a Claude Code skill that gives Anthropic’s AI assistant Metalama knowledge:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Conceptual documentation&lt;/li&gt;
  &lt;li&gt;API references&lt;/li&gt;
  &lt;li&gt;Sample code and pattern libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you’re new to Metalama or tackling a complex scenario, Claude can now provide contextually relevant guidance for aspect development, templates, fabrics, and the code model.&lt;/p&gt;

&lt;p&gt;The skill is available on the &lt;a href=&quot;https://github.com/metalama/Metalama.AI.Skills&quot;&gt;Metalama.AI.Skills marketplace&lt;/a&gt;. For setup instructions, see &lt;a href=&quot;https://doc.metalama.net/conceptual/using/claude-code&quot;&gt;Configuring Claude Code&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;documentation-updates&quot;&gt;Documentation updates&lt;/h2&gt;

&lt;p&gt;We’ve made these improvements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New: &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/type-system&quot;&gt;Working with types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Improved: &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/templates&quot;&gt;Writing T# templates&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Updated: &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/dependency-injection&quot;&gt;Injecting dependencies into aspects&lt;/a&gt; (now covers cross-project DI)&lt;/li&gt;
  &lt;li&gt;Updated: &lt;a href=&quot;https://doc.metalama.net/conceptual/aspects/advising/overriding-events&quot;&gt;Overriding events&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;New: &lt;a href=&quot;https://doc.metalama.net/conceptual/introspection/metrics&quot;&gt;Consuming code metrics&lt;/a&gt; and &lt;a href=&quot;https://doc.metalama.net/conceptual/sdk/custom-metrics&quot;&gt;Custom metrics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Enhanced API docs with integrated conceptual content&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;breaking-changes&quot;&gt;Breaking changes&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;.NET 6 SDK is no longer supported.&lt;/li&gt;
  &lt;li&gt;Several API and behavioral changes. See the &lt;a href=&quot;https://doc.metalama.net/conceptual/release-notes/release-notes-2026-0&quot;&gt;release notes&lt;/a&gt; for details.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;With 2026.0 shipped, we’ll focus on extending C# 14 support in aspects.&lt;/p&gt;

&lt;p&gt;Found an issue or have a feature request? Let us know on &lt;a href=&quot;https://github.com/metalama/Metalama/issues&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy meta-programming!&lt;/p&gt;

&lt;p&gt;-gael&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/metalama-2026-0-ga"&gt;Metalama 2026.0 Generally Available: Full Support for C# 14 and .NET 10&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Mon, 05 Jan 2026 07:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/metalama-2026-0-ga</link>
        <guid isPermaLink="true">https://postsharp.net/blog/metalama-2026-0-ga</guid>
        
        <category>featured</category>
        
        
        <category>Metalama</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2026/2026-01-announcement/metalama.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>Metalama November 2025 Update: Release Candidate for Metalama 2026.0</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2025/2025-11-status/november-dark.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;Metalama 2026.0 has reached Release Candidate status! All planned features are implemented, our test suite is green, and the release is stable enough for production evaluation. We’re now gathering community feedback ahead of our GA release on January 5th, 2026.&lt;/p&gt;

&lt;p&gt;Ready to try it? The RC packages are available on &lt;a href=&quot;https://www.nuget.org/packages/Metalama.Framework/2026.0.6-rc&quot;&gt;NuGet.org&lt;/a&gt;, and the Visual Studio extension can be downloaded from the &lt;a href=&quot;https://www.postsharp.net/downloads/metalama/metalama-2026.0&quot;&gt;Metalama 2026.0 downloads page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article covers what we shipped this month. For the complete list of changes in Metalama 2026.0, see the &lt;a href=&quot;https://doc.metalama.net/preview/conceptual/release-notes/release-notes-2026-0&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the full list of fixes and enhancements, see the changelogs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.4-preview&quot;&gt;2026.0.4-preview&lt;/a&gt; (November 8).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.5-preview&quot;&gt;2026.0.5-preview&lt;/a&gt; (November 12).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.6-rc&quot;&gt;2026.0.6-rc&lt;/a&gt; (November 28).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;c-14-extension-members&quot;&gt;C# 14 Extension Members&lt;/h2&gt;

&lt;p&gt;This month, we completed support for C# 14 extension blocks. You can now advise extension members and introduce members into existing extension blocks.&lt;/p&gt;

&lt;p&gt;Extension blocks are the “extend everything” feature in C# 14. Here’s how Metalama models them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Extension blocks use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IExtensionBlock&lt;/code&gt; interface, which implements &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeKind = Extension&lt;/code&gt;) so you can discover members the usual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fields&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Properties&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Methods&lt;/code&gt;, … collections.&lt;/li&gt;
  &lt;li&gt;They appear under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.ExtensionBlocks&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Extension methods and property accessors are also listed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.Methods&lt;/code&gt; as implicitly-implemented methods.&lt;/li&gt;
  &lt;li&gt;You can override extension members using the advising API or add aspects using custom attributes.&lt;/li&gt;
  &lt;li&gt;You can also add new extension members to existing extension blocks.&lt;/li&gt;
  &lt;li&gt;Introducing new extension blocks won’t be supported in 2026.0.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;other-improvements&quot;&gt;Other Improvements&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Single-file applications.&lt;/strong&gt; Metalama aspects now work in single-file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dotnet run&lt;/code&gt; applications: arguably a niche scenario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toast notifications.&lt;/strong&gt; Product briefs and news now appear via toast notifications on Windows. You can disable or configure this feature through the UI or CLI tool.&lt;/p&gt;

&lt;h2 id=&quot;visual-studio-tools-improved-stability-and-performance&quot;&gt;Visual Studio Tools improved stability and performance&lt;/h2&gt;

&lt;p&gt;During the last two weeks, we focused heavily on Visual Studio extension stability, and uncovered more issues than expected.&lt;/p&gt;

&lt;p&gt;We owe you an apology. Most of these bugs were already present in the 2025.1 release, though some may have been introduced by a Visual Studio 17.x minor update (we don’t repeat our full manual test suite after each VS release, so we can’t be certain). We discovered them through exhaustive testing on clean virtual machines as part of our RC validation process.&lt;/p&gt;

&lt;p&gt;This level of testing clearly wasn’t done properly for 2025.1. To ensure quality meets our standards, we chose to delay the release by one month, missing our target to reach GA before the Christmas break. It was the right call.&lt;/p&gt;

&lt;p&gt;The good news: the Visual Studio extension is now significantly more stable, and we improved performance along the way. You can download it from the &lt;a href=&quot;https://www.postsharp.net/downloads/metalama/metalama-2026.0&quot;&gt;Metalama 2026.0 downloads page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;known-issues&quot;&gt;Known Issues&lt;/h2&gt;

&lt;p&gt;A couple of items to address before GA:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There’s a known issue (&lt;a href=&quot;https://github.com/metalama/Metalama.Compiler/issues/149&quot;&gt;#149&lt;/a&gt;) with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt&lt;/code&gt; package on Linux. We’re working on a fix.&lt;/li&gt;
  &lt;li&gt;The next RC will update to Roslyn 5.0.0 GA (&lt;a href=&quot;https://github.com/metalama/Metalama/issues/1212&quot;&gt;#1212&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next&lt;/h2&gt;

&lt;p&gt;With full .NET 10 SDK and C# 14 support (except for by-design limitations documented in the &lt;a href=&quot;https://doc.metalama.net/preview/conceptual/release-notes/release-notes-2026-0&quot;&gt;release notes&lt;/a&gt;), and a significantly more stable Visual Studio extension, we’re on track for GA on January 5th, 2026.&lt;/p&gt;

&lt;p&gt;If you haven’t tried the RC yet, now is the time. Test it with your projects and let us know what you find. Your feedback helps us ship a stable release.&lt;/p&gt;

&lt;p&gt;Happy meta-programming!&lt;/p&gt;

&lt;p&gt;-gael&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/status-2025-11"&gt;Metalama November 2025 Update: Release Candidate for Metalama 2026.0&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Sun, 30 Nov 2025 07:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/status-2025-11</link>
        <guid isPermaLink="true">https://postsharp.net/blog/status-2025-11</guid>
        
        <category>featured</category>
        
        
        <category>Metalama</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2025/2025-11-status/november-dark.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>Metalama October 2025 Update: Full Steam Ahead Toward 2026.0</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2025/2025-10-status/october-dark.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;October is traditionally our busiest month. Microsoft ships the RCs of the .NET SDK, C# and Visual Studio, and we sprint to make Metalama ready. This year is no exception: we’ve made solid progress, and we’re confident we’ll be ready on time for the GA wave. Below is a recap of what we shipped and what’s coming.&lt;/p&gt;

&lt;h2 id=&quot;metalama-20252-skipped-for-simplicity&quot;&gt;Metalama 2025.2: skipped for simplicity&lt;/h2&gt;

&lt;p&gt;We’ve decided not to ship Metalama 2025.2 as a standalone release. All its features, including the ability to override event handler invocations, are already merged into Metalama 2026.0. Why? The only real benefit of releasing 2025.2 would be making event-invocation advising available a few weeks earlier, but supporting two versions in parallel would slow us down.&lt;/p&gt;

&lt;h2 id=&quot;metalama-20260-almost-there&quot;&gt;Metalama 2026.0: almost there&lt;/h2&gt;

&lt;p&gt;We are now almost code-complete with Metalama 2026.0, and have released several previews:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.3-preview&quot;&gt;2026.0.3-preview changelog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.2-preview&quot;&gt;2026.0.2-preview changelog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/metalama/Metalama/releases/tag/release%2F2026.0.1-preview&quot;&gt;2026.0.1-preview changelog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;net-10-sdk-and-c-14&quot;&gt;.NET 10 SDK and C# 14&lt;/h3&gt;

&lt;p&gt;We’re nearly done with support for the .NET 10 SDK and C# 14. Want to see where things stand? Check out these resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/orgs/metalama/projects/1/views/2?sliceBy%5Bvalue%5D=2026.0&quot;&gt;General status board&lt;/a&gt; highlighting the leftovers for the 2026.0 version.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/orgs/metalama/projects/1/views/14&quot;&gt;C# 14 status board&lt;/a&gt; showing our progress with C# 14 features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Out of scope for Metalama 2026.0:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Using null-conditional assignments in templates. &lt;a href=&quot;https://github.com/metalama/Metalama/issues/1109&quot;&gt;#1109&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field&lt;/code&gt; keyword in templates. &lt;a href=&quot;https://github.com/metalama/Metalama/issues/1114&quot;&gt;#1114&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Introducing new extension blocks. &lt;a href=&quot;https://github.com/metalama/Metalama/issues/1159&quot;&gt;#1159&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;del&gt;Introducing extension members into existing extension blocks. &lt;a href=&quot;https://github.com/metalama/Metalama/issues/1160&quot;&gt;#1160&lt;/a&gt;&lt;/del&gt; UPDATE: implemented in 2026.0.4-preview.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fun fact&lt;/strong&gt;: we noticed that compiling our &lt;a href=&quot;https://github.com/metalama/Metalama.Tests.NopCommerce&quot;&gt;NopCommerce snapshot&lt;/a&gt; with C# 14 breaks LINQ-to-SQL because of implicit conversions of arrays to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadOnlySpan&lt;/code&gt;. We’ve had to pin this solution to C# 13 to work around this issue.&lt;/p&gt;

&lt;h3 id=&quot;extension-blocks&quot;&gt;Extension blocks&lt;/h3&gt;

&lt;p&gt;“Extend everything” is the headline feature of C# 14, and we’re making sure Metalama supports it out of the box, including overriding extension members. Here’s how we’re modeling extension blocks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Extension blocks use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IExtensionBlock&lt;/code&gt; interface (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeKind = Extension&lt;/code&gt;). It derives from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType&lt;/code&gt;, and adds two properties: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReceiverParameter&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReceiverType&lt;/code&gt;. Although extension blocks derive from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType&lt;/code&gt;, you can’t always treat them like regular ones. Yes, this technically bends the Liskov Substitution Principle, but splitting the hierarchy would make the API noisier for little practical benefit. For extension members (except classic extension methods), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IMember.DeclaringType&lt;/code&gt; points to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IExtensionBlock&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Extension blocks show up under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.ExtensionBlocks&lt;/code&gt;, not as nested types (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.Types&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Extension methods and property accessors are listed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.Methods&lt;/code&gt; as implicitly-implemented methods. They exist in IL and are addressable in C#, but you can’t override them with Metalama.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach feels natural for C# developers and closely matches Roslyn’s model.&lt;/p&gt;

&lt;h3 id=&quot;first-class-support-for-named-tuples&quot;&gt;First-class support for named tuples&lt;/h3&gt;

&lt;p&gt;Previously, Metalama treated tuples as plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType&lt;/code&gt; objects, without access to element types or names. This made scenarios like packing method arguments for interceptors (think caching) awkward and inefficient. Now, with the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITupleType&lt;/code&gt; interface, you get direct access to element names and types. Create named tuples with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeFactory.CreateTupleType&lt;/code&gt;, and instantiate them with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITupleType.CreateCreateInstanceExpression&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our implementation even supports tuples with zero or one element. For two or more, you get the nice tuple syntax; for degenerate cases, Metalama falls back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValueTuple.Create(...)&lt;/code&gt;. When you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITupleType&lt;/code&gt;, you don’t have to worry about these details yourself.&lt;/p&gt;

&lt;p&gt;Example: Want to advise multiple methods and pass all arguments to an observer? Here’s how:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Create the tuple type.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TypeFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateTupleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create the tuple instance.&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleExpression&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateCreateInstanceExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Invoke the interceptor.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;_myObserver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OnMethodCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DeclaringType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tupleExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Transformed code:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Two or more arguments: tuple syntax&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IEnumerable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Hat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FindHats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;decimal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_myObserver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OnMethodCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;HatStore&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FindHats&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// One argument: ValueTuple.Create&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;IsHatAvailable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hatId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_myObserver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OnMethodCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;HatStore&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;IsHatAvailable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ValueTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hatId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Zero arguments&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;IsStoreOpen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_myObserver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;OnMethodCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;HatStore&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;IsStoreOpen&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ValueTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p class=&quot;note&quot;&gt;&lt;strong&gt;Breaking Change:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INamedType.TypeKind&lt;/code&gt; now returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tuple&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NamedType&lt;/code&gt; for tuples.&lt;/p&gt;

&lt;h3 id=&quot;advising-event-invocations&quot;&gt;Advising event invocations&lt;/h3&gt;

&lt;p&gt;Overriding event handler invocation logic, originally planned for 2025.2, is now part of 2026.0. For details, see the &lt;a href=&quot;/blog/status-2025-09#metalama-20252-rc-event-invocation-overrides&quot;&gt;September 2025 Status Update&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;other-improvements&quot;&gt;Other improvements&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Introducing user-defined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checked&lt;/code&gt; operators.&lt;/li&gt;
  &lt;li&gt;Dependency injection: pull constructor parameters across projects.&lt;/li&gt;
  &lt;li&gt;API cleanup (some breaking changes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Obsolete]&lt;/code&gt; warnings).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;metalama-20251-now-supports-visual-studio-2026&quot;&gt;Metalama 2025.1: now supports Visual Studio 2026&lt;/h2&gt;

&lt;p&gt;Last month, we added limited .NET 10 SDK support to Metalama 2025.1. As of October 7, Visual Studio 2026 is also supported.&lt;/p&gt;

&lt;p&gt;Just make sure to update both the NuGet packages and the VSIX extension.&lt;/p&gt;

&lt;h2 id=&quot;roadmap-finalizing-20260&quot;&gt;Roadmap: finalizing 2026.0&lt;/h2&gt;

&lt;p&gt;We’re wrapping up the last features for full C# 14 support in Metalama 2026.0. Next up: stabilization, code cleanup, manual testing, and performance validation.&lt;/p&gt;

&lt;p&gt;We’re aiming for a release candidate (RC) on November 7, barring any surprises during testing. The final GA release will follow soon after Microsoft ships the GA versions of the .NET SDK and related packages.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In October, we made good progress on Metalama 2026.0, whose main focus is to support the .NET 10 SDK, C# 14, and Visual Studio 2026. We’re almost code complete, and we’ll spend most of November stabilizing the release.&lt;/p&gt;

&lt;p&gt;Happy meta-programming!&lt;/p&gt;

&lt;p&gt;-gael&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/status-2025-10"&gt;Metalama October 2025 Update: Full Steam Ahead Toward 2026.0&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Thu, 30 Oct 2025 07:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/status-2025-10</link>
        <guid isPermaLink="true">https://postsharp.net/blog/status-2025-10</guid>
        
        <category>featured</category>
        
        
        <category>Metalama</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2025/2025-10-status/october-dark.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>Metalama Status Update, September 2025</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2025/2025-09-status/september-dark.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;Welcome to Metalama’s September 2025 status update. After a relaxed summer, we’re back in full swing, delivering .NET 10 SDK support for Metalama and closing a key gap versus PostSharp: the ability to override event handler invocations.&lt;/p&gt;

&lt;h2 id=&quot;our-first-community-contributor&quot;&gt;Our first community contributor&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/2025/2025-09-status/beppemarazzi.jpeg&quot; alt=&quot;Giuseppe Marazzi&quot; class=&quot;portrait&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let me start with the announcement that brings me the greatest joy.&lt;/p&gt;

&lt;p&gt;This past summer, Metalama received its first contribution from the open-source community. &lt;a href=&quot;https://github.com/beppemarazzi&quot;&gt;Giuseppe Marazzi&lt;/a&gt; submitted &lt;a href=&quot;https://github.com/metalama/Metalama/pulls?q=author%3Abeppemarazzi++is%3Apr&amp;amp;filterScopeGroup=true&quot;&gt;two PRs&lt;/a&gt; fixing two small and hard-to-find bugs.&lt;/p&gt;

&lt;p&gt;A warm thanks to Giuseppe!&lt;/p&gt;

&lt;p&gt;While Metalama may look like a complex codebase at first glance, Giuseppe’s contribution proves that anyone can make a meaningful impact. Don’t let the technical depth intimidate you: every contribution counts, however small. Our &lt;a href=&quot;https://doc.metalama.net/contributing&quot;&gt;contributor’s guide&lt;/a&gt; shows you where to start.&lt;/p&gt;

&lt;h2 id=&quot;net-sdk-10-readiness&quot;&gt;.NET SDK 10 readiness&lt;/h2&gt;

&lt;p&gt;As autumn arrives, Microsoft is finalizing the new .NET stack, and, like all .NET extenders, we’re working hard to make sure you can use the new features as soon as possible.&lt;/p&gt;

&lt;p&gt;We’ve split the work into two releases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Metalama 2025.1 received quick fixes to keep working with the .NET 10 SDK, with limitations;&lt;/li&gt;
  &lt;li&gt;Metalama 2026.0 will be built natively for the .NET 10 SDK.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;metalama-20251-limited-net-sdk-10-support&quot;&gt;Metalama 2025.1: limited .NET SDK 10 support&lt;/h3&gt;

&lt;p&gt;With the .NET SDK 10 already in RC, we didn’t want you to wait for full integration, so we made small changes to ensure compatibility with the new .NET SDK.&lt;/p&gt;

&lt;p&gt;This build is Metalama 2025.1.14, released this week. From our &lt;a href=&quot;https://github.com/metalama/Metalama.Tests.DotNetSdk/actions/workflows/test.yml&quot;&gt;platform integration matrix tests&lt;/a&gt;, most .NET workloads are working.&lt;/p&gt;

&lt;p&gt;Keep in mind that Metalama 2025.1 is still based on Roslyn 4.14, while the .NET SDK 10 includes Roslyn 5.0. This has some implications:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Analyzers and source generators compiled against Roslyn 5.0 will not work. When possible, we replace them with an older Roslyn 4.14 version. This often works, but not always.&lt;/li&gt;
  &lt;li&gt;Specifically, Blazor projects (all flavors) are not supported yet because of an incompatibility in their source generators.&lt;/li&gt;
  &lt;li&gt;You cannot use C# 14 features in your Metalama projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;metalama-20260-in-progress&quot;&gt;Metalama 2026.0 in progress&lt;/h3&gt;

&lt;p&gt;The goal of Metalama 2026.0 is to bring full native support for the .NET 10 SDK and C# 14: native, not hacks.&lt;/p&gt;

&lt;p&gt;C# 14 brings a lot of new features, and we won’t support all of them in every scenario in November, when the new .NET is expected to become generally available. Our primary goal with Metalama 2026.0 is to let you safely use any new C# feature in your runtime code, but not necessarily in aspect templates. Support for new language features in templates may come in later versions. This aligns with our design philosophy: Metalama should be able to compile any valid C# code, but it’s okay to limit features available in aspects.&lt;/p&gt;

&lt;p&gt;We’re using GitHub to track our progress. You can use &lt;a href=&quot;https://github.com/metalama/Metalama/issues/1045&quot;&gt;this meta-issue&lt;/a&gt; or &lt;a href=&quot;https://github.com/orgs/metalama/projects/1/views/2?sliceBy%5Bvalue%5D=2026.0&quot;&gt;this dashboard&lt;/a&gt; to check the status.&lt;/p&gt;

&lt;p&gt;We plan to have an RC ready in November, when Microsoft is expected to release the new stack.&lt;/p&gt;

&lt;p&gt;If you’re eager for a preview, look for one next week. Or, if you’re more patient, compile the develop/2026.0 branch of &lt;a href=&quot;https://github.com/metalama/Metalama/tree/develop/2026.0&quot;&gt;Metalama&lt;/a&gt; and &lt;a href=&quot;https://github.com/metalama/Metalama.Compiler/tree/develop/2026.0&quot;&gt;Metalama.Compiler&lt;/a&gt; repos (merged from Roslyn tag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NET-SDK-10.0.100-preview.7.25380.108&lt;/code&gt; as of today).&lt;/p&gt;

&lt;h2 id=&quot;visual-studio-2026-readiness&quot;&gt;Visual Studio 2026 readiness&lt;/h2&gt;

&lt;p&gt;We ran some initial tests of our Metalama Tools for Visual Studio with Visual Studio 2026. They failed, subtly but miserably.&lt;/p&gt;

&lt;p&gt;It seems those incompatibilities can be addressed with fairly small bug fixes. If that proves to be true, we’ll update our tooling 2025.1 to support Visual Studio 2026, and there will be no need to wait for Metalama 2026.0.&lt;/p&gt;

&lt;h2 id=&quot;metalama-20252-rc-event-invocation-overrides&quot;&gt;Metalama 2025.2 RC: Event invocation overrides&lt;/h2&gt;

&lt;p&gt;We have just released the first (and hopefully final) RC of Metalama 2025.2.&lt;/p&gt;

&lt;p&gt;Since the beginning, Metalama has allowed overriding the &lt;em&gt;add&lt;/em&gt; and &lt;em&gt;remove&lt;/em&gt; accessors of events, which were arguably of limited utility. This version adds the ability to override the &lt;em&gt;invocation&lt;/em&gt; of event handlers. The OverrideInvoke method of the OverrideEventAspect class lets you intercept the invocation of an individual event handler.&lt;/p&gt;

&lt;p&gt;Typical use cases are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;safe events (exception handling)&lt;/li&gt;
  &lt;li&gt;background/asynchronous events&lt;/li&gt;
  &lt;li&gt;event invocation logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s illustrate this with an example. This aspect catches exceptions in event handlers; if any exception is caught, it removes it from the event invocation list.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SafeEventAttribute&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OverrideEventAspect&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// If there are many event handlers, this method will be called several times.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OverrideInvoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Proceed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;// First time shame on you, second time shame on me.&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can now add this to any event:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Camera&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SafeEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnFocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you might expect, it took us a while to implement. It’s far from simple.&lt;/p&gt;

&lt;p&gt;Here’s how Metalama transforms your code:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Camera&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// The field backing the event.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_focusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// A broker sitting between the event API and the backing field.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ActionEventBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_focusChangedBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Binds the broker to the event implementation and the advice.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ActionEventBrokerCallbacks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FocusChangedBrokerCallbacks_0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Camera&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FocusChanged_Invoke_SafeEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Camera&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FocusChanged_SafeEvent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Camera&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FocusChanged_SafeEvent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;



    &lt;span class=&quot;c1&quot;&gt;// The public event with the new implementation.&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SafeEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FocusChanged&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;add&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ActionEventBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;EnsureInitialized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_focusChangedBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FocusChangedBrokerCallbacks_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_focusChangedBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AddHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;remove&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_focusChangedBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RemoveHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// The original event implementation.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FocusChanged_SafeEvent&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;add&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_focusChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;remove&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_focusChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Your advice intercepting the handler invocation.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FocusChanged_Invoke_SafeEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_focusChanged&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnFocusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_focusChanged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EventArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a bit lengthy, but aside from a touch of syntactic sugar, the event broker is the most reliable pattern, because we can’t predict or analyze how an event is raised. This approach is oblivious to the event’s implementation and to how it gets raised.&lt;/p&gt;

&lt;p&gt;You can find more details on this &lt;a href=&quot;https://doc.metalama.net/preview/conceptual/aspects/advising/overriding-events&quot;&gt;documentation page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Subscribe to our &lt;a href=&quot;/metalama/briefs&quot;&gt;briefs&lt;/a&gt; to receive updates about ongoing work on Metalama 2026.0 before the next monthly update.&lt;/p&gt;

&lt;h2 id=&quot;dockerization-of-our-build-infrastructure&quot;&gt;Dockerization of our build infrastructure&lt;/h2&gt;

&lt;p&gt;As a side note, the entire Metalama build infrastructure now runs on Docker, requiring only lean build agents.&lt;/p&gt;

&lt;p&gt;That means you can build Metalama in the exact environment we use.&lt;/p&gt;

&lt;p&gt;All you need is a Windows 11 or Windows Server 2025 machine with Docker installed and Windows containers enabled, then run:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\DockerBuild.ps1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;On the feature side, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OverrideEventAspect.OverrideInvoke&lt;/code&gt; advice closes one of Metalama’s remaining gaps with PostSharp. On the platform front, we’ve released the first bits of .NET 10 support and we expect to deliver more soon. In terms of infrastructure, Dockerizing our build workflow makes Metalama easy to reproduce across agents and helps reduce the cost and complexity of our setup.&lt;/p&gt;

&lt;p&gt;Happy meta-programming with Metalama!&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/status-2025-09"&gt;Metalama Status Update, September 2025&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Wed, 01 Oct 2025 07:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/status-2025-09</link>
        <guid isPermaLink="true">https://postsharp.net/blog/status-2025-09</guid>
        
        <category>featured</category>
        
        
        <category>Metalama</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2025/2025-09-status/september-dark.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>Security Notice: Data Leak Affecting a Limited Number of Accounts</title>
        <description>
           
          &lt;p&gt;We regret to inform you of a data leak that occurred on the &lt;strong&gt;PostSharp Customer Portal&lt;/strong&gt; between &lt;strong&gt;Wednesday, September 3rd, and Tuesday, September 9th&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;who-is-affected&quot;&gt;Who is affected?&lt;/h3&gt;

&lt;p&gt;A total of &lt;strong&gt;38 customer accounts&lt;/strong&gt; were impacted. If your account was affected, you will:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Receive a personal notification email within the next 24 hours.&lt;/li&gt;
  &lt;li&gt;Notice that you can no longer sign in to the portal using your license keys.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;what-data-was-leaked&quot;&gt;What data was leaked?&lt;/h3&gt;

&lt;p&gt;Only the content of the &lt;a href=&quot;https://www.postsharp.net/account&quot;&gt;https://www.postsharp.net/account&lt;/a&gt; page of the portal was exposed, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Company name and billing address (or customer name and address for natural persons)&lt;/li&gt;
  &lt;li&gt;All subscription dates, number of users, licensed products, and support level&lt;/li&gt;
  &lt;li&gt;All license keys for PostSharp and Metalama&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-was-not-leaked&quot;&gt;What was &lt;em&gt;not&lt;/em&gt; leaked?&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Contact lists or email addresses&lt;/li&gt;
  &lt;li&gt;Prices, invoices, or quotes&lt;/li&gt;
  &lt;li&gt;Support tickets&lt;/li&gt;
  &lt;li&gt;Source code (never uploaded to our servers)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;who-accessed-the-data&quot;&gt;Who accessed the data?&lt;/h3&gt;

&lt;p&gt;At most, &lt;strong&gt;one other PostSharp customer&lt;/strong&gt; may have received your data in error.&lt;/p&gt;

&lt;h3 id=&quot;how-did-this-happen&quot;&gt;How did this happen?&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;caching error&lt;/strong&gt; occurred in the daily job that sends subscription renewal notifications, causing account data to be sent to the wrong recipient. The first customer of the batch received all emails.&lt;/p&gt;

&lt;h3 id=&quot;timeline-of-events&quot;&gt;Timeline of events&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Wed 9/3, 11:00 AM&lt;/strong&gt; – First incorrect email sent.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Mon 9/8, 8:00 PM&lt;/strong&gt; – Data leak reported by the receiving customer.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tue 9/9, 2:00 PM&lt;/strong&gt; – Report read and incident confirmed.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tue 9/9, 4:30 PM&lt;/strong&gt; – Credentials invalidated and issue remediated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-we-fixed-it&quot;&gt;How we fixed it?&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;All past &lt;strong&gt;magic URLs&lt;/strong&gt; were invalidated by rotating the salt for each affected account.&lt;/li&gt;
  &lt;li&gt;License keys exposed in the leak were &lt;strong&gt;disabled for authentication&lt;/strong&gt; to the portal.&lt;/li&gt;
  &lt;li&gt;The caching bug was fixed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;do-you-need-to-take-action&quot;&gt;Do you need to take action?&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No action is required&lt;/strong&gt;. Your license keys will continue to work normally with PostSharp and Metalama products.&lt;/li&gt;
  &lt;li&gt;If you prefer, we can issue &lt;strong&gt;new license keys&lt;/strong&gt; on request, to ensure that any leaked key cannot be used by another party.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-to-log-in-now&quot;&gt;How to log in now?&lt;/h3&gt;

&lt;p&gt;If your license keys no longer work for portal login:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;strong&gt;email authentication&lt;/strong&gt; (one-time PIN or magic link) for one of your account contacts.&lt;/li&gt;
  &lt;li&gt;If you do not know your contact, please write to &lt;strong&gt;&lt;a href=&quot;mailto:hello@postsharp.net&quot;&gt;hello@postsharp.net&lt;/a&gt;&lt;/strong&gt; from your work email.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We take full responsibility for this incident and sincerely apologize for the error. We are committed to ensuring it does not happen again.&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/2025-09-09-security-notice"&gt;Security Notice: Data Leak Affecting a Limited Number of Accounts&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Sun, 07 Sep 2025 23:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/2025-09-09-security-notice</link>
        <guid isPermaLink="true">https://postsharp.net/blog/2025-09-09-security-notice</guid>
        
        
        <category>PostSharp</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/blog/ps-no-featimg-16x9.jpg</url>
          
        </image>
      </item>
    
      <item>
        <title>Breaking Update of PostSharp Caching adapter for Redis in 2025.1</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2025/2025-09-redis-caching/caching.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;We have released a refactored version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PostSharp.Patterns.Caching.Backends.Redis&lt;/code&gt; in PostSharp 2025.1 to address a reliability issue that could surface in multi-node Redis deployments (master/replica or cluster) when cache dependencies are enabled under sustained load. The fix required a redesign of the internal data schema, which is why this is a breaking change (one-time cache purge). Outside of that purge, the upgrade is straightforward and brings measurable gains in performance, consistency, and resilience.&lt;/p&gt;

&lt;p&gt;Impact at a glance:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;If you run multi-node Redis with dependencies, the update removes a potential failure mode.&lt;/li&gt;
  &lt;li&gt;You only need a one-time cache purge, and you’ll still benefit from performance and diagnostics improvements.&lt;/li&gt;
  &lt;li&gt;There is no risk of user data loss; only old cached entries stay in the database until purged.&lt;/li&gt;
  &lt;li&gt;No impact for the other backends.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;who-is-affected&quot;&gt;Who is affected?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Affected by the bug:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Applications that use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PostSharp.Patterns.Caching.Backends.Redis&lt;/code&gt; with support for dependencies in a Redis master/replica or cluster setup.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Affected by the refactoring:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;All applications that use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PostSharp.Patterns.Caching.Backends.Redis&lt;/code&gt;, with or without support for dependencies, are affected by the redesign of the data schema. You must purge the cache after the update, and there is no other impact. All versions prior to 2025.1.7 are affected.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Customers using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Metalama.Patterns.Caching.Backends.Redis&lt;/code&gt; are affected by this issue too, and the solution has not yet been ported to Metalama. Please contact us if it matters to you.&lt;/p&gt;

&lt;h2 id=&quot;what-was-wrong&quot;&gt;What was wrong?&lt;/h2&gt;

&lt;p&gt;The previous design of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RedisCachingBackend&lt;/code&gt; relied on a retry loop in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetItem&lt;/code&gt; operations to retrieve a consistent snapshot of the cache item, which includes both the cache value and its dependencies, stored in separate Redis keys. Under heavy load in a master/replica setup, this loop could exhaust its iterations and fail.&lt;/p&gt;

&lt;p&gt;The consistent snapshot of value and dependencies was required because recursive dependencies (when a cached method calls another already cached method) were flattened in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetItem&lt;/code&gt; operation, so the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RemoveItem&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InvalidateItem&lt;/code&gt; operations did not need to operate recursively. This was a poor design choice.&lt;/p&gt;

&lt;p&gt;The previous component was only tested in a single-node Redis topology. We believe the root cause was a lack of testing in multi-node topologies under high load.&lt;/p&gt;

&lt;h2 id=&quot;how-was-this-fixed&quot;&gt;How was this fixed?&lt;/h2&gt;

&lt;p&gt;We redesigned the data schema so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetItem&lt;/code&gt; never needs to iterate:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Dependencies are no longer flattened. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RemoveItem&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InvalidateItem&lt;/code&gt; operations now work recursively.&lt;/li&gt;
  &lt;li&gt;Cache keys (a single logical cache item requires several Redis keys) are now versioned, so we don’t need loops to ensure read consistency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-else-has-been-improved&quot;&gt;What else has been improved?&lt;/h2&gt;

&lt;p&gt;Since a major refactoring was required to implement the new data schema, we went the extra mile and made the component more resilient in high-load production environments:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Performance improvements&lt;/strong&gt; due to the new design of the Redis data schema that is always observationally consistent for read operations.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Key compression (hashing).&lt;/strong&gt; Enable this feature by assigning the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CachingServices.DefaultKeyBuilder&lt;/code&gt; property.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;More resilient&lt;/strong&gt; thanks to new behaviors controlled by the following properties on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RedisCachingBackendConfiguration&lt;/code&gt; object:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Exception handling:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RedisCachingBackendConfiguration.ExceptionHandlingPolicy&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Retry policies:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RedisCachingBackendConfiguration.BackgroundRecoveryRetryPolicy&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RedisCachingBackendConfiguration.BackgroundTasksRetryPolicy&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RedisCachingBackendConfiguration.TransactionRetryPolicy&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Concurrency control:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BackgroundTasksMaxConcurrency&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InvalidationMaxConcurrency&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Node selection:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReadCommandFlags&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteCommandFlags&lt;/code&gt;, defaulting to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreferReplica&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PreferMaster&lt;/code&gt;, respectively.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Support for sharding clusters,&lt;/strong&gt; with keys containing taghashes. Tested on a 3+3 cluster.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Support for dependencies&lt;/strong&gt; with a very large number of dependent cache items.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GC process:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Detection of overloads and automatic temporary disabling.&lt;/li&gt;
      &lt;li&gt;Periodic background cleanups to handle situations that were not detected by processing keyspace notifications in real time.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Keys contain the PostSharp Caching schema version&lt;/strong&gt; for safe updates.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fixed bugs&lt;/strong&gt; with sliding expiration.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Improved &lt;a href=&quot;https://doc.postsharp.net/caching/backends/caching-redis&quot;&gt;documentation&lt;/a&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-changes-are-breaking&quot;&gt;What changes are breaking?&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The data schema has changed, so you must purge the old version’s cache; otherwise it will contain permanently unreachable data (garbage) forever.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CacheValue.Dependencies&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CacheItem.Dependencies&lt;/code&gt; properties now contain first-level dependencies rather than all recursive dependencies. These objects are largely implementation details and do not surface to the aspect-oriented API of PostSharp Caching.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-to-update&quot;&gt;How to update?&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Update all PostSharp packages to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2025.1.8&lt;/code&gt; and deploy your application.&lt;/li&gt;
  &lt;li&gt;Purge the cache using Redis’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FLUSHDB&lt;/code&gt; command after your old application has been undeployed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you ignore this post and only update the package, the Redis database will contain the data of the old version forever, since the dependency-management keys are set to never expire.&lt;/p&gt;

&lt;h2 id=&quot;read-more&quot;&gt;Read more&lt;/h2&gt;

&lt;p&gt;For details about the refactored PostSharp Caching for Redis, see our &lt;a href=&quot;https://doc.postsharp.net/caching/backends/caching-redis&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;PostSharp Caching for Redis now runs on a more robust, versioned schema that removes a reliability edge case and improves performance and consistency across single-node, replicated, and sharded clusters when dependency support is enabled. The component has been overhauled for better observability and resilience. The only required action is a one-time cache purge after upgrading to 2025.1.8 or later.&lt;/p&gt;

&lt;p&gt;If you rely on the Metalama Redis backend, let us know so we can prioritize porting the same improvements.&lt;/p&gt;

&lt;p&gt;Thanks to customers who surfaced the scenario early—enjoy the improved backend.&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/redis-caching-update"&gt;Breaking Update of PostSharp Caching adapter for Redis in 2025.1&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Mon, 01 Sep 2025 23:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/redis-caching-update</link>
        <guid isPermaLink="true">https://postsharp.net/blog/redis-caching-update</guid>
        
        
        <category>PostSharp</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2025/2025-09-redis-caching/caching.svg</url>
          
        </image>
      </item>
    
      <item>
        <title>PostSharp Is Now Source Available</title>
        <description>
           
          &lt;img src="https://postsharp.net/assets/images/2025/2025-08-source-available/postsharp.svg" style="width: 100%"/&gt;
          
          &lt;p&gt;This spring we open-sourced Metalama. Continuing that push for transparency and dependability, PostSharp’s source code is now available to enterprise customers at no extra cost. You can access a read-only mirror of our primary Git repository, including every version back to 1.0 (2009). It’s an exact copy of the repo we use to build the product — down to the commas. We also provide a supported, Docker-based build for versions 2024.0, 2025.0, and 2025.1. Those versions are no longer obfuscated in our public builds.&lt;/p&gt;

&lt;p&gt;The code is released under a permissive, proprietary source-available license. You can modify, build, and distribute the software, provided users of the modified code hold a valid PostSharp license.&lt;/p&gt;

&lt;p&gt;We are releasing our source code with the following use cases in mind:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Troubleshooting&lt;/li&gt;
  &lt;li&gt;Supply chain security&lt;/li&gt;
  &lt;li&gt;Supply chain resilience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an era of tightening regulations (like the EU’s Cyber Resilience Act) and increased focus on software supply chain security, transparency isn’t optional — it’s necessary.&lt;/p&gt;

&lt;h2 id=&quot;who-qualifies&quot;&gt;Who qualifies&lt;/h2&gt;

&lt;p&gt;To access the source, you need an Enterprise E1 support plan or higher, which is included in:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;a 10-user subscription of PostSharp Ultimate, or&lt;/li&gt;
  &lt;li&gt;a 15-user subscription of PostSharp Framework.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s no additional cost — it’s included in your subscription.&lt;/p&gt;

&lt;p&gt;If you have fewer users but need source access, add more users to your subscription.&lt;/p&gt;

&lt;p&gt;See our &lt;a href=&quot;https://www.postsharp.net/support/policies/sla&quot;&gt;support policies&lt;/a&gt; for a description of our support levels and their eligibility.&lt;/p&gt;

&lt;p&gt;Before getting access to the repo, you must sign a Non-Disclosure &amp;amp; Non-Competing Agreement.&lt;/p&gt;

&lt;h2 id=&quot;use-case-1-troubleshooting&quot;&gt;Use case 1. Troubleshooting&lt;/h2&gt;

&lt;p&gt;You now have full visibility into the source to troubleshoot issues.&lt;/p&gt;

&lt;p&gt;We’ve disabled obfuscation in all maintained versions. When decompilation isn’t sufficient, you can read the original source.&lt;/p&gt;

&lt;p&gt;Note: SourceLink is not available yet.&lt;/p&gt;

&lt;h2 id=&quot;use-case-2-supply-chain-security&quot;&gt;Use case 2. Supply chain security&lt;/h2&gt;

&lt;p&gt;Supply chain security isn’t just about trusting suppliers — it’s about trusting the code you run. With full access to our source, you can run your own analysis tools and assess the code’s quality.&lt;/p&gt;

&lt;p&gt;Auditing the source alone isn’t enough. You need to guarantee that the binaries you execute were built from that audited source. That means you should be able to build the code yourself. To make that practical, we provide a Docker-based build that requires only Windows containers.&lt;/p&gt;

&lt;p&gt;Once you’ve built the packages, you have two theoretical options to verify the chain of custody:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use the packages you built yourself instead of sourcing them from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nuget.org&lt;/code&gt;, or&lt;/li&gt;
  &lt;li&gt;Compare your packages with those sourced publicly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In practice, our public binaries won’t be bitwise identical to what you build because our public builds are signed with Authenticode using a timestamp and a private certificate we cannot share. For that reason, only the first option — using your own built packages — is available to guarantee the chain of custody.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href=&quot;https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping&quot;&gt;Package Source Mapping&lt;/a&gt; (a NuGet client option) to ensure packages are sourced from your private builds rather than PostSharp’s public ones.&lt;/p&gt;

&lt;h2 id=&quot;use-case-3-supply-chain-resilience&quot;&gt;Use case 3. Supply chain resilience&lt;/h2&gt;

&lt;p&gt;Companies rely on PostSharp for mission-critical applications and need contingency plans for scenarios such as product end-of-life, company closure, or temporary inability of the supplier to deliver fixes or platform updates. By giving enterprise customers full source access, we enable practical contingency plans. You have the legal right and technical capability to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fork and maintain your own version of PostSharp if our support becomes unavailable&lt;/li&gt;
  &lt;li&gt;Apply critical security patches without waiting for official updates&lt;/li&gt;
  &lt;li&gt;Maintain older versions beyond their official support lifecycle&lt;/li&gt;
  &lt;li&gt;Ensure business continuity even in worst-case scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Section 9 of the &lt;a href=&quot;https://www.postsharp.net/downloads/legal/PostSharp%20License%20and%20Support%20Services%20Agreement%202025-Q2.docx&quot;&gt;license agreement&lt;/a&gt; provides the legal framework for these business continuity scenarios, so you can be confident your critical systems won’t be held hostage by vendor dependencies.&lt;/p&gt;

&lt;h2 id=&quot;how-does-it-work&quot;&gt;How does it work?&lt;/h2&gt;

&lt;h3 id=&quot;1-getting-access&quot;&gt;1. Getting access&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Sign in to the &lt;a href=&quot;https://www.postsharp.net/account&quot;&gt;customer portal&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Check your support entitlements. You must have an Enterprise support plan (E1 or higher).&lt;/li&gt;
  &lt;li&gt;Go to the &lt;a href=&quot;https://www.postsharp.net/account/source-access&quot;&gt;source access&lt;/a&gt; page.&lt;/li&gt;
  &lt;li&gt;Sign the Non-Disclosure/Non-Competing Agreement online (or offline).&lt;/li&gt;
  &lt;li&gt;Allow one business day for review and account update.&lt;/li&gt;
  &lt;li&gt;Return to the &lt;a href=&quot;https://www.postsharp.net/account/source-access&quot;&gt;source access&lt;/a&gt; page and create Git users and passwords.&lt;/li&gt;
  &lt;li&gt;Clone the repositories using Git.&lt;/li&gt;
  &lt;li&gt;Check out one of the support release branches: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;release/2024.0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;release/2025.0&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;release/2025.1&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;2-building-packages&quot;&gt;2. Building packages&lt;/h3&gt;

&lt;p&gt;See &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt; in the cloned repo for details about requirements and build instructions.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You need a Windows 11 machine with Docker Desktop configured for Windows containers.&lt;/li&gt;
  &lt;li&gt;Open a PowerShell prompt and execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./Build-Docker.ps1&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Wait — initial image creation can take over an hour on a high-end notebook; subsequent builds may take around 30 minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;getting-support&quot;&gt;Getting support&lt;/h2&gt;

&lt;p&gt;We’re here to help. Enterprise customers can email support@postsharp.net for help with source access, builds, or questions about the source-available license. Customers with Enterprise E2 support plans or higher can also reach us on Microsoft Teams or Slack for real-time collaboration and faster resolution of complex issues.&lt;/p&gt;

&lt;h2 id=&quot;limitations&quot;&gt;Limitations&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The source code of Visual Studio Tools for Metalama and PostSharp is currently not available.&lt;/li&gt;
  &lt;li&gt;Our obligation is limited to a successful Docker build from the unmodified source:
    &lt;ul&gt;
      &lt;li&gt;Although the repo includes CI/CD scripts, running those tests or configuring CI/CD infrastructure is not supported.&lt;/li&gt;
      &lt;li&gt;We do not provide support for modified source code.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;We only support building release branches for currently maintained versions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Publishing PostSharp’s source is the final step in our 2025 transparency and dependability initiative, following Metalama’s earlier move to open source. Eligible customers now have full access to the source, improving supplier security and resilience.&lt;/p&gt;

&lt;p&gt;If you want access, visit the &lt;a href=&quot;https://www.postsharp.net/account&quot;&gt;PostSharp Customer Portal&lt;/a&gt; to verify your eligibility, complete the NDA/NCA process, and gain repository access.&lt;/p&gt;


          &lt;p&gt;
            This article was first published on a &lt;a href="https://metalama.net/blog"&gt;https://metalama.net/blog&lt;/a&gt;
            under the title &lt;a href="https://postsharp.net/blog/postsharp-source-available"&gt;PostSharp Is Now Source Available&lt;/a&gt;.
          &lt;/p&gt;
        </description>
        <pubDate>Thu, 07 Aug 2025 23:00:01 +0000</pubDate>
        
        <link>https://postsharp.net/blog/postsharp-source-available</link>
        <guid isPermaLink="true">https://postsharp.net/blog/postsharp-source-available</guid>
        
        
        <category>PostSharp</category>
        
        <image>
          
          <url>https://postsharp.net/assets/images/2025/2025-08-source-available/postsharp.svg</url>
          
        </image>
      </item>
    
  </channel>
</rss>
