### Install and Run DiffEngineTray Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/testing/diff-tool.md Install the DiffEngineTray global tool using the dotnet CLI and then run it to manage snapshot changes from the system tray. ```powershell dotnet tool install -g DiffEngineTray diffenginetray ``` -------------------------------- ### Example: Caching with Redis Backend Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/redis.md Demonstrates how to use Metalama Caching with Redis as the backend, updating a previous example to utilize Redis instead of MemoryCache. ```csharp // This is a test class, not intended for direct use. // It serves as an example of how caching attributes interact with the Redis backend. [GenerateTransformations] public class RedisCachingTests { [GenerateCachingPolicy(Duration = 1000)] public async Task GetValueAsync(int id) { await Task.Delay(100); // Simulate work return $"Value for {id}"; } [GenerateCachingPolicy(Duration = 1000)] public async Task SetValueAsync(int id, string value) { await Task.Delay(100); // Simulate work } } ``` -------------------------------- ### Logging Example with Dependency Injection Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/troubleshooting.md A complete example demonstrating Metalama caching with detailed logging enabled via dependency injection. Observe program output for caching events. ```csharp using Metalama.Patterns.Caching.Building; using Metalama.Patterns.Caching.Implementation; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; // Configure services with logging and Metalama caching. var services = new ServiceCollection(); services.AddLogging(builder => builder.SetMinimumLevel(LogLevel.Debug)); services.AddMetalamaCaching(); var serviceProvider = services.BuildServiceProvider(); // Get the caching service. var cachingService = serviceProvider.GetRequiredService(); // Example usage of the caching service. var cacheKey = "my-cache-key"; var cachedValue = await cachingService.GetOrSetAsync(cacheKey, async () => { await Task.Delay(100); // Simulate work return "my-cached-value"; }); Console.WriteLine($"Retrieved value: {cachedValue}"); ``` -------------------------------- ### Install dotnet-dump Tool Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/configuration/process-dump.md Installs the global `dotnet-dump` tool, which is required for collecting process dumps. ```powershell dotnet tool install --global dotnet-dump ``` -------------------------------- ### Path Resolution Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/claude/SKILL.md Demonstrates how the '~/' path prefix resolves to the SKILLS.md directory. ```markdown [~/code/Metalama.Documentation.SampleCode.AspectFramework/GettingStarted/GettingStarted.cs] ``` -------------------------------- ### Simulated Distributed Application with Azure Service Bus Synchronization Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/pubsub.md Example demonstrating a multi-instance application where cache instances are synchronized using Azure Service Bus. This setup ensures consistency across different application instances accessing a shared database. ```csharp using Metalama.Patterns.Caching; using Metalama.Patterns.Caching.Backends.Azure; using Metalama.Patterns.Caching.Building; using System.Collections.Concurrent; namespace Metalama.Documentation.SampleCode.Caching.AzureSynchronized; public class AzureSynchronized { public static async Task ExampleAsync() { var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(); // Configure caching with in-memory backend and Azure Service Bus synchronization. serviceCollection.AddMetalamaCaching( cachingBuilder => cachingBuilder.WithBackend(backendBuilder => backendBuilder.Memory()) .WithAzureSynchronization("UseDevelopmentStorage=true")); var serviceProvider = serviceCollection.BuildServiceProvider(); var cachingService = serviceProvider.GetRequiredService(); await cachingService.InitializeAsync(); // Simulate two instances of the application. var instance1 = new CacheInstance(cachingService, "Instance1"); var instance2 = new CacheInstance(cachingService, "Instance2"); // Instance 1 writes a value. await instance1.WriteValueAsync("myKey", "myValue1"); // Instance 2 reads the value (should be synchronized). var value2 = await instance2.ReadValueAsync("myKey"); Console.WriteLine($"{instance2.Name} read: {value2}"); // Instance 2 writes a different value. await instance2.WriteValueAsync("myKey", "myValue2"); // Instance 1 reads the updated value. var value1 = await instance1.ReadValueAsync("myKey"); Console.WriteLine($"{instance1.Name} read: {value1}"); await cachingService.DisposeAsync(); } } public class CacheInstance { private readonly ICachingService _cachingService; private readonly string _name; private readonly ConcurrentDictionary _database; public string Name => _name; public CacheInstance(ICachingService cachingService, string name) { _cachingService = cachingService; _name = name; _database = new ConcurrentDictionary(); } public async Task WriteValueAsync(string key, string value) { Console.WriteLine($"{_name} writing '{value}' to key '{key}'..."); _database[key] = value; await _cachingService.SetAsync(key, value, TimeSpan.FromMinutes(5)); Console.WriteLine($"{_name} finished writing."); } public async Task ReadValueAsync(string key) { Console.WriteLine($"{_name} reading key '{key}'..."); var value = await _cachingService.GetAsync(key); Console.WriteLine($"{_name} finished reading. Value: {value}"); return value; } } ``` -------------------------------- ### Install HTML Writer Package Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/testing/snapshot-testing.md Install the Metalama.Extensions.HtmlWriter package to generate syntax-highlighted HTML representations of your code, useful for documentation. ```xml ``` -------------------------------- ### Example: Four Ways to Call Interface Members Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/implementing-interfaces.md Demonstrates all four approaches to call an introduced Dispose method from another template. ```cs using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using Metalama.Framework.Validation; namespace Metalama.Documentation.SampleCode.AspectFramework; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter)] public class ImplementInterfaceFourWaysAttribute : Aspect { public override void BuildAspect(BuildAspectContext context) { context.Enhance(context.Target.Type.ImplementInterface(typeof(IDisposable))); } } public interface IDisposable { void Dispose(); } [ImplementInterfaceFourWays] public class MyDisposableClass : IDisposable { public void Dispose() { // This method is introduced by the aspect. // The following demonstrates how to call it from another template. // Option 1. Access the aspect template member this.Dispose(); // Option 2. Use meta.This and write dynamic code meta.This.Dispose(); // Option 3. Use invokers IMethod disposeMethod = meta.This.Type.Methods.Single(m => m.Name == nameof(IDisposable.Dispose)); disposeMethod.Invoke(); // Option 4. Cast to interface ((IDisposable) meta.This).Dispose(); } } ``` -------------------------------- ### Architecture Verification Tool Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/introspection/workspaces.md Demonstrates an architecture verification tool that checks naming conventions and namespace dependencies using Metalama workspaces. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Diagnostics; using Metalama.Framework.Introspection; using Metalama.Framework.Workspaces; namespace Metalama.Documentation.SampleCode.Workspaces; public class Program { public static void Main( string[] args ) { var workspace = Workspace.Create(); // Report violations and track counts workspace.SourceCode.Types .Where( t => t.Name.StartsWith( "_" ) ) .Report( Severity.Warning, "NAMING001", "Type names should not start with underscore." ); Console.WriteLine( $"Found {DiagnosticReporter.ReportedWarnings} warnings." ); // Example: architecture verification // This tool checks naming conventions and namespace dependencies. workspace.SourceCode.Types .Where( t => t.Name.StartsWith( "_" ) ) .Report( Severity.Warning, "NAMING001", "Type names should not start with underscore." ); workspace.SourceCode.Types .SelectMany( t => t.NestedTypes ) .Where( nt => nt.Namespace != t.Namespace ) .Report( Severity.Error, "NSDEP001", "Nested types must be in the same namespace as their parent type." ); Console.WriteLine( $"Found {DiagnosticReporter.ReportedErrors} errors." ); } } ``` -------------------------------- ### Email, Phone, and Url Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Demonstrates the use of EmailAttribute, PhoneAttribute, and UrlAttribute for validating common string formats. ```csharp using Metalama.Patterns.Contracts; public class WellKnownRegexContracts { [Email] public string Email { get; set; } [Phone] public string PhoneNumber { get; set; } [Url] public string WebsiteUrl { get; set; } } ``` -------------------------------- ### Standalone Code Complexity Analyzer Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/introspection/metrics.md This example demonstrates a complete standalone tool using the Workspaces API to analyze code complexity and report on methods exceeding a threshold. ```csharp using Metalama.Extensions.Metrics; using Metalama.Framework.Code; using Metalama.Framework.Workspaces; using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; namespace Metalama.Documentation.SampleCode.Metrics.Workspaces; public static class Program { public static void Main(string[] args) { var services = new ServiceCollection(); services.AddMetrics(); // Register metric providers var workspace = services.BuildServiceProvider().GetRequiredService(); // Replace with the actual path to your solution or project. workspace.LoadSolutionAsync("../../../../Metalama.sln").Wait(); var complexMethods = workspace.Projects .SelectMany(p => p.Documents) .SelectMany(d => d.SyntaxTree.GetRoot().DescendantNodes().OfType()) .Where(m => m.Metrics().Get().Value > 50) .Select(m => (m.ContainingType.Name, m.Name, m.Metrics().Get().Value)); Console.WriteLine("Complex methods:"); foreach (var (type, method, count) in complexMethods) { Console.WriteLine($"- {type}.{method}: {count} syntax nodes"); } } } ``` -------------------------------- ### StringLength Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Shows how to use the StringLengthAttribute to enforce minimum and maximum length for a string. ```csharp using Metalama.Patterns.Contracts; public class StringLengthContract { [StringLength(5, 10)] public string Description { get; set; } } ``` -------------------------------- ### Contract Inheritance Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/adding-contracts.md Demonstrates how contracts applied to interface members are automatically inherited by implementing classes. ```csharp public interface ICustomer { [NotEmpty] string Name { get; } } public class Customer : ICustomer { public string Name { get; set; } = "John Doe"; } ``` -------------------------------- ### Enumerate MethodInfos Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/templates/reflection.md This example demonstrates how to retrieve all methods of a target type as System.Reflection.MethodInfo objects using Metalama. ```csharp using Metalama.Framework.Aspect; using Metalama.Framework.Code; using System.Reflection; public class EnumerateMethodInfosAttribute : TypeAspect { public override void BuildAspect( IAspectBuilder builder ) { builder.AdviseMethods(AdviseMethod); } private void AdviseMethod( MethodAspectContext context ) { // This aspect does not modify the method. } public static MethodInfo[] GetMethodInfos( Type type ) { var compileTimeType = type.ToCompileTime(); var methods = new List(); foreach ( var method in compileTimeType.Methods ) { methods.Add( method.ToMethodInfo() ); } return methods.ToArray(); } } ``` -------------------------------- ### Example: String dependencies in ProductCatalogue Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/dependencies.md Demonstrates how to use string dependencies for read and write methods in a product catalogue scenario. It models dependencies for product lists, individual product prices, and a complete price list. ```csharp using Metalama.Patterns.Caching; using Metalama.Patterns.Caching.Dependencies; using Metalama.Patterns.Caching.Implementation; namespace Metalama.Documentation.SampleCode.Caching.StringDependencies; [ProvideCachingService] internal partial class ProductCatalogue { private readonly ICachingService _cachingService; // Dependencies for the product list without prices. [Cache] public string[] GetProducts() => new[] { "Product A", "Product B" }; // Dependencies for the price of a specific product. [Cache] public decimal GetPrice(int productId) { this._cachingService.AddDependency($"ProductPrice:{productId}"); return productId * 10m; } // Dependencies for the list of all products with their prices. [Cache] public (string Name, decimal Price)[] GetPriceList() { this._cachingService.AddDependency("ProductList"); this._cachingService.AddDependency("PriceList"); return new[] { ("Product A", 10m), ("Product B", 20m) }; } // Invalidate product list and price list dependencies. public void AddProduct(string name) { this._cachingService.Invalidate("ProductList"); this._cachingService.Invalidate("PriceList"); } // Invalidate specific product price and the complete price list dependencies. public void UpdatePrice(int productId, decimal newPrice) { this._cachingService.Invalidate($"ProductPrice:{productId}"); this._cachingService.Invalidate("PriceList"); } } ``` -------------------------------- ### Configure Metalama Caching with Redis Backend (DI) Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/redis.md Integrate the Redis caching backend into Metalama Caching by calling WithBackend and providing a delegate that configures the Redis caching factory. This example shows the setup within a dependency injection container. ```csharp serviceCollection.AddMetalamaCaching(builder => builder.WithBackend(RedisCachingFactory.Redis)); ``` -------------------------------- ### Install Metalama Command Line Tool Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/installing/dotnet-tool.md Use this command to install the Metalama command line tool globally. After installation, the 'metalama' command will be available in your system's PATH. ```powershell dotnet tool install -g metalama.tool ``` -------------------------------- ### Install Metalama Plugin in Claude Code Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/claude/README.md Install the Metalama plugin after adding its marketplace to Claude Code. ```bash /plugin install metalama ``` -------------------------------- ### Running Redis Dependency GC Process Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/redis.md Demonstrates how to set up and run the Redis dependency garbage collection process using Microsoft.Extensions.Hosting. Ensure the GC process is running to manage cache dependencies effectively. ```csharp using Metalama.Patterns.Caching.Backends.Redis; using Metalama.Patterns.Caching.Implementation; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; await Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { services.AddMetalamaCaching(options => { options.AddRedisDistributedCache("my-redis-cache", redisOptions => { redisOptions.Configuration = "localhost:6379"; redisOptions.InstanceName = "my-instance"; redisOptions.SupportsDependencies = true; }); }); // Add the Redis dependency garbage collector. services.AddRedisCacheDependencyGarbageCollector(); }) .Build() .RunAsync(); ``` -------------------------------- ### Example Aspect for Testing Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/testing/snapshot-testing.md This is an example of an aspect that can be tested. It's typically placed in a separate file within a class library project. ```cs [metalama-test ~/code/Metalama.Documentation.SampleCode.AspectFramework/Testing.TheAspect.cs name="Main"] ``` -------------------------------- ### Initializer Ordering Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/initializers.md Demonstrates the matryoshka rule for ordering initializers when multiple aspects and inheritance levels are involved. Exercises BeforeBase and AfterBase initializers for AfterLastInstanceConstructor. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using System; namespace Metalama.Documentation.SampleCode.AspectFramework; public enum AspectOrderDirection { RunTime, CompileTime } [AttributeUsage( AttributeTargets.Assembly )] public class AspectOrderAttribute : Attribute { public AspectOrderAttribute( AspectOrderDirection direction, params Type[] aspectTypes ) { Direction = direction; AspectTypes = aspectTypes; } public AspectOrderDirection Direction { get; } public Type[] AspectTypes { get; } } public abstract class BaseAspect : Aspect { protected void AddInitializers( IAspectReceiver receiver, string messagePrefix ) { // BeforeBase initializer. receiver.AdviseAfterLastInstanceConstructor( (context, next) => { Console.WriteLine( "{0} {1}.BeforeBase: {2}", messagePrefix, context.Target.Type.Name, "base call" ); next( context ); } ); // AfterBase initializer. receiver.AdviseAfterLastInstanceConstructor( (context, next) => { next( context ); Console.WriteLine( "{0} {1}.AfterBase: {2}", messagePrefix, context.Target.Type.Name, "base call" ); } ); } } [AspectOrder( AspectOrderDirection.RunTime, typeof( AspectA ), typeof( AspectB ) )] public class AspectA : BaseAspect { public override void BuildAspect( IAspectBuilder builder ) { builder.Advise( OnClassBuild ); } private void OnClassBuild( IClassDeclaration classDeclaration, IAspectReceiver receiver ) { AddInitializers( receiver, "AspectA" ); } } public class AspectB : BaseAspect { public override void BuildAspect( IAspectBuilder builder ) { builder.Advise( OnClassBuild ); } private void OnClassBuild( IClassDeclaration classDeclaration, IAspectReceiver receiver ) { AddInitializers( receiver, "AspectB" ); } } [AspectA, AspectB] public class BaseClass { public BaseClass() { Console.WriteLine( "BaseClass.Constructor" ); } public virtual void OnConstructed() { Console.WriteLine( "BaseClass.OnConstructed" ); } public virtual void Initialize() { Console.WriteLine( "BaseClass.Initialize" ); } } [AspectA, AspectB] public class DerivedClass : BaseClass { public DerivedClass() { Console.WriteLine( "DerivedClass.Constructor" ); } public override void OnConstructed() { Console.WriteLine( "DerivedClass.OnConstructed" ); base.OnConstructed(); } public override void Initialize() { Console.WriteLine( "DerivedClass.Initialize" ); base.Initialize(); } } ``` -------------------------------- ### Introduce Guid Property Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/initializers.md Introduces an 'Id' property of type Guid and initializes it to a new unique value using a declarative approach. ```csharp public class IntroduceIdAttribute : IntroduceMemberAspect { public override void BuildAspectOf(AspectInfo aspectInfo) { aspectInfo.IntroduceProperty("Id") .WithInitializer(new Guid(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); } } ``` -------------------------------- ### Example Option Class Implementation Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/configuration/exposing-options.md Demonstrates a typical implementation of IHierarchicalOptions. The class has no explicit constructor, init-only nullable properties, and an ApplyChanges method for merging configurations. ```csharp using Metalama.Framework.Options; namespace Metalama.Documentation.SampleCode.AspectFramework; public class AspectConfigurationOptions : IHierarchicalOptions, IHierarchicalOptions, IHierarchicalOptions, IHierarchicalOptions { public string? CacheDirectory { get; init; } public int? CacheDurationInSeconds { get; init; } public AspectConfigurationOptions ApplyChanges(AspectConfigurationOptions? changes) { if (changes == null) { return this; } return new AspectConfigurationOptions { CacheDirectory = changes.CacheDirectory ?? this.CacheDirectory, CacheDurationInSeconds = changes.CacheDurationInSeconds ?? this.CacheDurationInSeconds }; } public AspectConfigurationOptions GetDefaultOptions(IProject project) { return this; } AspectConfigurationOptions IHierarchicalOptions.ApplyChanges(AspectConfigurationOptions? changes) { return ApplyChanges(changes); } AspectConfigurationOptions IHierarchicalOptions.ApplyChanges(AspectConfigurationOptions? changes) { return ApplyChanges(changes); } AspectConfigurationOptions IHierarchicalOptions.ApplyChanges(AspectConfigurationOptions? changes) { return ApplyChanges(changes); } AspectConfigurationOptions IHierarchicalOptions.ApplyChanges(AspectConfigurationOptions? changes) { return ApplyChanges(changes); } } ``` -------------------------------- ### Implementing a Hashing Cache Key Builder Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/caching-keys.md This example demonstrates how to implement a custom `ICacheKeyBuilder` that hashes the generated cache key using the XxHash128 algorithm. It reuses the default string-based builder for generating the initial key string. ```csharp using Metalama.Patterns.Caching.Formatters; using Metalama.Patterns.Caching.Utilities; using System.Security.Cryptography; public class HashingCacheKeyBuilder : CacheKeyBuilder { private readonly bool _useXxHash128; public HashingCacheKeyBuilder(bool useXxHash128 = true) { _useXxHash128 = useXxHash128; } public override string BuildKey(CacheKeyBuilderArgs args) { var key = base.BuildKey(args); if (_useXxHash128) { // Use XxHash128 for good performance and low collision rate. var hashBytes = RandomNumberGenerator.GetBytes(16); var hasher = new XxHash128(); hasher.Append(key); hasher.GetHashAndReset(hashBytes); return Convert.ToHexString(hashBytes); } else { // Fallback to SHA256 if XxHash128 is not available or desired. using var sha256 = SHA256.Create(); var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(key)); return Convert.ToHexString(hashBytes); } } } ``` -------------------------------- ### Tuple Interceptor Aspect Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/type-system.md An aspect demonstrating packing all method arguments into a tuple for interception and then unpacking them. This example highlights the simplicity of working with tuples regardless of parameter count. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using System; using System.Collections.Generic; using System.Linq; namespace Metalama.Documentation.SampleCode.AspectFramework; public class TupleInterceptorAttribute : TypeAspect { public override void BuildAspect( IAspectBuilder builder ) { builder.AdviseMethod( m => m.IsPublic && !m.IsStatic && !m.IsAbstract && m.DeclaringType.IsPublic, AdviseMethod.Introduce, AdviseMethod.Intercept, AdviseMethod.Override ); } public void Intercept( IMethodFabric method, dynamic[] arguments ) { var tupleType = method.Parameters.Select( p => (p.Type, p.Name) ).ToArray(); var tuple = method.Parameters.Select( p => arguments[p.Index] ).ToArray(); var tupleInstance = method.Parameters.CreateTupleInstanceExpression( tuple ).Value; // Call the original method with the unpacked arguments. method.Invoke( tupleInstance ); } public void Override( IMethodFabric method, dynamic[] arguments ) { // This method is not called because Intercept is used. throw new NotImplementedException(); } public void Introduce( IMethodFabric method ) { // This method is not called because Intercept is used. throw new NotImplementedException(); } } ``` -------------------------------- ### Aspect Execution Order Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/multiple-instances/ordering.md Demonstrates two aspects applied in a specific order (Aspect1 < Aspect2). Aspect2 is applied first, then Aspect1, and finally the original method. ```csharp /* This code is part of a larger example and demonstrates the effect of aspect ordering. It defines two aspects, Aspect1 and Aspect2, which add a method to a target type. The execution order is defined as Aspect1 < Aspect2, meaning Aspect2 is applied first, followed by Aspect1, and then the original method body. */ // Assume Aspect1 and Aspect2 are defined elsewhere and implement the ordering logic. // The following is a conceptual representation of the outcome. public class TargetClass { public void SourceMethod() { // Original method body System.Console.WriteLine("Original method executed."); } } // Aspect1 and Aspect2 would typically be derived from Metalama.Framework.Aspects.Aspect // and would contain logic to modify the TargetClass, for example: /* // Example of Aspect1's potential modification (conceptual) public class Aspect1 : Aspect { public override void BuildAspect() { // ... logic to add methods or modify existing ones ... // Aspect1's code runs after Aspect2's code in this scenario. System.Console.WriteLine("Aspect1 executed."); } } // Example of Aspect2's potential modification (conceptual) public class Aspect2 : Aspect { public override void BuildAspect() { // ... logic to add methods or modify existing ones ... // Aspect2's code runs before Aspect1's code in this scenario. System.Console.WriteLine("Aspect2 executed."); } } */ // The actual code for the Metalama test would be in a separate file (e.g., Ordering.cs) // and would contain the [assembly: AspectOrder] attribute and the aspect definitions. // The output of the test would show the execution order. ``` -------------------------------- ### Registering a License Key via CLI Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/installing/register-license.md Use the `metalama license register` command to register a license key from the command line. Replace `` with your actual license. ```bash metalama license register ``` -------------------------------- ### Get Metric Value from Declaration Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/introspection/metrics.md Use the Metrics() extension method and Get() to retrieve metric values for a declaration. The Value property holds the metric's numerical result. ```csharp var syntaxNodeCount = method.Metrics().Get(); int count = syntaxNodeCount.Value; ``` -------------------------------- ### Load Workspace and Query Metrics Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/introspection/metrics.md After registering providers, load the workspace and query metrics using the standard Metrics() extension method. ```csharp var workspace = ...; // Load your workspace var syntaxNodeCount = workspace.Projects.SelectMany(p => p.Documents).First() .SyntaxTree.GetRoot() .DescendantNodes() .OfType() .First() .Metrics() .Get(); Console.WriteLine($"Syntax node count: {syntaxNodeCount.Value}"); ``` -------------------------------- ### Examples of Named Types in C# Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/type-system.md Illustrates various kinds of named types in C#, including classes, records, structs, interfaces, enums, delegates, generic types, nested types, and tuple types. These examples showcase the declaration syntax for each type. ```csharp public class Customer; public record Person(string Name, int Age); public struct Point; public record struct Point( float X, float Y ); public interface IRepository; public enum Status; public delegate void EventHandler(); public class List; public class Customer { public class Builder; } (string Name, int Age) ``` -------------------------------- ### Required Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Illustrates the RequiredAttribute, which checks for non-null and non-empty strings. ```csharp using Metalama.Patterns.Contracts; public class RequiredContract { [Required] public string Name { get; set; } } ``` -------------------------------- ### Load a Solution using Workspace Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/introspection/workspaces.md Load a solution file directly using the Workspace.Load method. Provide the full path to the solution file. ```csharp var workspace = Workspace.Load( @"C:\src\MySolution.sln" ); ``` -------------------------------- ### Introduce Operators for IEquatable Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/introducing-members.md This example demonstrates introducing the equality (`==`, `!=`) and `GetHashCode` operators to a type, implementing the `IEquatable` interface. It compares public automatic properties and fields using the default comparer. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using Metalama.Framework.Validation; namespace Metalama.Documentation.SampleCode.AspectFramework; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] public class IntroduceOperatorAttribute : TypeAspect { public override void BuildAspect( IAspectBuilder aspectBuilder ) { aspectBuilder.Advise( type => type.ImplementInterface( typeof( IEquatable ) ) ); } public override void BuildMembers( IMemberAspectBuilder memberAspectBuilder ) { memberAspectBuilder.Advise( type => { type.IntroduceMethod( nameof( GetHashCode ) ) .With( buildMethod => { buildMethod.OperatorKind = OperatorKind.GetHashCode; } ); type.IntroduceMethod( "==" ) .With( buildMethod => { buildMethod.OperatorKind = OperatorKind.Addition; buildMethod.Parameters.Add( aspectBuilder.ParameterBuilder.Build( typeof( T ) ) ); buildMethod.Parameters.Add( aspectBuilder.ParameterBuilder.Build( typeof( T ) ) ); buildMethod.ReturnType = aspectBuilder.TypeBuilder.Build( typeof( bool ) ); } ); type.IntroduceMethod( "!=" ) .With( buildMethod => { buildMethod.OperatorKind = OperatorKind.Subtraction; buildMethod.Parameters.Add( aspectBuilder.ParameterBuilder.Build( typeof( T ) ) ); buildMethod.Parameters.Add( aspectBuilder.ParameterBuilder.Build( typeof( T ) ) ); buildMethod.ReturnType = aspectBuilder.TypeBuilder.Build( typeof( bool ) ); } ); } ); } } public class IntroduceOperator : IntroduceOperatorAttribute { public override void BuildMembers( IMemberAspectBuilder memberAspectBuilder ) { base.BuildMembers( memberAspectBuilder ); } } ``` -------------------------------- ### NotNull Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Demonstrates the usage of the NotNullAttribute to ensure a value is not null. ```csharp using Metalama.Patterns.Contracts; public class NotNullContract { [NotNull] public string Message { get; set; } } ``` -------------------------------- ### Create a Dependent Project for Multi-Project Tests Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/testing/snapshot-testing.md Structure a multi-project test by creating a dependent project file named Foo.Dependency.cs, where Foo.cs is the principal test file. ```mermaid graph BT Foo -- references --> Foo.Dependency ``` -------------------------------- ### Build Metalama Project Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/README.md Use this command to build the entire Metalama project. Ensure you are in the root directory of the repository. ```powershell .\Build.ps1 build ``` -------------------------------- ### CreditCard Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Shows how to use the CreditCardAttribute to validate a string as a credit card number. ```csharp using Metalama.Patterns.Contracts; public class CreditCardContract { [CreditCard] public string CreditCardNumber { get; set; } } ``` -------------------------------- ### Manually Import YourProject.props for ProjectReference Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/configuration/msbuild-properties.md This XML snippet shows how to manually import the `YourProject.props` file when a project references your library using a `ProjectReference`. This is an alternative to the NuGet package inclusion method. ```xml ``` -------------------------------- ### Observable Attribute Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/observability/observability.md Demonstrates the generated code for a simple class implementing INotifyPropertyChanged using the ObservableAttribute. ```csharp using System.ComponentModel; namespace Metalama.Documentation.SampleCode.Observability { public class ComputedProperty : INotifyPropertyChanged { private string _firstName; private string _lastName; public string FirstName { get => _firstName; set { if (value == _firstName) { return; } _firstName = value; OnPropertyChanged(); } } public string LastName { get => _lastName; set { if (value == _lastName) { return; } _lastName = value; OnPropertyChanged(); } } public string FullName => $"{FirstName} {LastName}"; public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ``` -------------------------------- ### Specific Templates for All Kinds of Methods Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/overriding-methods.md This example demonstrates implementing specific template methods for async, iterator, and async iterator methods, enabling iterator streaming and overcoming default template limitations. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using Metalama.Framework.Validation; namespace Metalama.Documentation.SampleCode.AspectFramework; [ProvideAspect(typeof (OverrideMethodAspect))] public class SpecificTemplateAllKindsAspect : OverrideMethodAspect { public override void OverrideMethod( OverrideMethodAspect.OverrideMethodArgs args ) { // No implementation needed here, as we are implementing specific template methods. } public override async Task OverrideAsyncMethod( OverrideMethodAspect.OverrideAsyncMethodArgs args ) { // You can use 'await' here. await args.ProceedAsync(); } public override IEnumerable OverrideEnumerableMethod( OverrideMethodAspect.OverrideEnumerableMethodArgs args ) { // You can use 'yield return' here. foreach ( var item in args.ProceedEnumerable() ) { yield return item; } } public override IEnumerator OverrideEnumeratorMethod( OverrideMethodAspect.OverrideEnumeratorMethodArgs args ) { // You can use 'yield return' here. foreach ( var item in args.ProceedEnumerator() ) { yield return item; } } public override async IAsyncEnumerable OverrideAsyncEnumerableMethod( OverrideMethodAspect.OverrideAsyncEnumerableMethodArgs args ) { // You can use 'await' and 'yield return' here. await foreach ( var item in args.ProceedAsyncEnumerable() ) { yield return item; } } public override async IAsyncEnumerator OverrideAsyncEnumeratorMethod( OverrideMethodAspect.OverrideAsyncEnumeratorMethodArgs args ) { // You can use 'await' and 'yield return' here. await foreach ( var item in args.ProceedAsyncEnumerator() ) { yield return item; } } } ``` -------------------------------- ### Configure Caching Profiles at Run Time Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/configuring.md Demonstrates how to configure caching profiles at run time by adding them to the service collection. This allows caching options to be loaded from external configuration sources. ```csharp using Metalama.Patterns.Caching.Building; using Metalama.Patterns.Caching.CachingServices; using Metalama.Patterns.Caching.Aspects; using Microsoft.Extensions.DependencyInjection; var serviceCollection = new ServiceCollection(); serviceCollection.AddMetalamaCaching( builder => { builder.AddProfile( "hot", c => c.WithSlidingExpiration( TimeSpan.FromMinutes( 5 ) ) ); builder.AddProfile( "default", c => c.WithAbsoluteExpiration( TimeSpan.FromMinutes( 10 ) ) ); } ); var cachingService = CachingService.Create( serviceCollection.BuildServiceProvider() ); [Cache( "hot" )] public class ProductCatalogue { [CacheEntry( "hot" )] public string GetProduct( int id ) { // ... return "Product " + id; } } ``` -------------------------------- ### Mixed Initialization Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/initializers.md Demonstrates how a custom aspect integrates with user-defined OnConstructed and Initialize methods. The aspect tracks lifecycle states, while the target class handles instance freezing and cross-property validation. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using System; using System.Collections.Generic; namespace Metalama.Documentation.SampleCode.AspectFramework; public class TrackLifecycleAttribute : Aspect { public override void BuildAspect( IAspectBuilder builder ) { builder.Advise( OnClassBuild ); } private void OnClassBuild( IClassDeclaration classDeclaration, IAspectReceiver receiver ) { // Track construction. receiver.AdviseInstanceConstructor( (context, next) => { TrackLifecycle.Register( context.Target.Type, LifecycleState.BeingConstructed ); next( context ); } ); // Track construction completion. receiver.AdviseAfterLastInstanceConstructor( (context, next) => { TrackLifecycle.Register( context.Target.Type, LifecycleState.Constructed ); next( context ); } ); // Track initialization completion. receiver.AdviseObjectInitializer( (context, next) => { TrackLifecycle.Register( context.Target.Type, LifecycleState.Initialized ); next( context ); } ); } } public static class TrackLifecycle { private static readonly Dictionary> s_registry = new(); public static void Register( Type type, LifecycleState state ) { Console.WriteLine( "Registering {0} for {1}", state, type.Name ); s_registry.Add( type, new List() ); s_registry[type].Add( state ); } } public enum LifecycleState { BeingConstructed, Constructed, Initialized } [TrackLifecycle] public class Customer { private readonly HashSet _tags = new(); // This method is called by the aspect. public void OnConstructed( object? tagCollection ) { Console.WriteLine( "Customer.OnConstructed" ); // Freeze the tag collection. // _tags.Add( "premium" ); } // This method is called by the aspect. public void Initialize() { Console.WriteLine( "Customer.Initialize" ); // Perform cross-property validation. // if ( _tags.Contains( "premium" ) && _name == null ) // { // throw new InvalidOperationException( "Name must be specified for premium customers." ); // } } } ``` -------------------------------- ### Install DiffEngine Extension Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/testing/diff-tool.md Add the Metalama.Extensions.DiffEngine optional package to your test project to enable diff tool integration. ```xml ``` -------------------------------- ### EnumDataType Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Demonstrates the usage of the EnumDataTypeAttribute to validate string, object, or integer types against a specified enum. ```csharp using Metalama.Patterns.Contracts; public enum Status { Pending, Processing, Completed, Failed } public class Order { [EnumDataType( typeof( Status ) )] public string Status { get; set; } } ``` -------------------------------- ### Binary-compatible parameter with forwarding constructors Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/introducing-constructor-parameters.md This example demonstrates an aspect that introduces a required DateTime parameter to all constructors. The framework generates forwarding constructors that supply DateTime.Now as the default value, preserving binary compatibility. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; using Metalama.Framework.RunTime; namespace Metalama.Documentation.SampleCode.AspectFramework; public class IntroduceRequiredParameterAttribute : Aspect { public override void BuildAspect( IAspectBuilder builder ) { builder.Advise( builder.Target.Method.Constructors.Select( c => c.DeclaringType.FullName != "System.Object" ), new IntroduceParameterAction ( "creationTime", ParameterDirection.Parameter, new PullStrategy.IntroduceParameterAndPull( new PullStrategy.UseExpression( "DateTime.Now" ) ) ) ); } } [IntroduceRequiredParameter] public class MyClass { public string Name { get; } public MyClass( string name ) { Name = name; } } public class MyClassWithObsoleteForwarder : MyClass { // This constructor is generated by the framework. // [Obsolete("Use MyClass(string name, DateTime creationTime) instead.")] // public MyClassWithObsoleteForwarder( string name ) // : base( name, DateTime.Now ) // { // } public MyClassWithObsoleteForwarder( string name, DateTime creationTime ) : base( name ) { // The 'creationTime' parameter is not used here because it is only // used by the forwarding constructor. } } ``` -------------------------------- ### Contract on Return Value Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/adding-contracts.md Shows how to apply a contract to the return value of a method using the [return: Contract] syntax. The contract is validated upon method exit. ```csharp public interface ICustomerService { [return: NotEmpty] string GetCustomerName(); } public class CustomerService : ICustomerService { public string GetCustomerName() => "John Doe"; } ``` -------------------------------- ### Custom Regular Expression Contract Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/contracts/contract-types.md Illustrates using the RegularExpressionAttribute to validate a string against a custom regex pattern. ```csharp using Metalama.Patterns.Contracts; public class CustomRegexContract { [RegularExpression("^ABC-\\d{3}$")] public string CustomCode { get; set; } } ``` -------------------------------- ### Configuring License in licensing.json Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/installing/register-license.md Manually set the license key by editing the `licensing.json` file. Ensure the file is located in the `%appdata%\Metalama` (Windows) or `~/.metalama` (Linux/Mac) directory. Replace the placeholder with your actual license key. ```json { "license": "123-ABCDEFGHIJKLMNOPQRSTUVXYZ" } ``` -------------------------------- ### Cache Method Example Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/patterns/caching/invalidation.md This C# code defines a read method that can be cached. It demonstrates how to mark a method for caching. ```csharp using Metalama.Patterns.Caching; namespace Metalama.Documentation.SampleCode.Caching.ImperativeInvalidate { public class PriceCatalogue { [Cache] // Marker for caching public virtual IEnumerable GetProducts(string category = "All") { // Simulate fetching data return new List(); } [Cache] // Marker for caching public virtual Product GetPrice(int productId) { // Simulate fetching data return new Product(); } public void AddProduct(Product product) { // Simulate adding data } public void UpdatePrice(int productId, decimal newPrice) { // Simulate updating data } } } ``` -------------------------------- ### Allowing Static Types Only Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/eligibility.md This example shows how to ensure an aspect is used only with static types by using EligibilityExtensions.DeclaringType().MustBeStatic(). ```csharp using Metalama.Framework.Aspect; using Metalama.Framework.Eligibility; public class StaticOnlyAttribute : Aspect, IEligible { public void BuildEligibility(IEligibilityBuilder builder) { builder.DeclaringType().MustBeStatic(); } public override TypeKind FormatterCategory => TypeKind.Any; public override void BuildAspect(AspectBuildContext context) { // Implementation omitted for brevity. } } ``` -------------------------------- ### Validating and Publishing an Order Object Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/initializers.md This example demonstrates applying `[Validate]` and `[Publish]` aspects to an `Order` hierarchy. It shows how to use `AspectOrder` to control the runtime execution of these aspects, ensuring validation occurs before publishing. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.RunTime; namespace Metalama.Documentation.SampleCode.AspectFramework; public class Order { public string Name { get; set; } } [Validate] [Publish] public class ValidatedOrder : Order { } public class ValidateAttribute : AspectAttribute { public override void BuildAspect(BuildAspectArgs args) { args.Enhancer.AddInitializer(this.ValidateOrder, InitializerPosition.Before); } private void ValidateOrder(Order order, InitializationContext context) { Console.WriteLine($"Validating order '{order.Name}'..."); // Simulate validation logic if (string.IsNullOrEmpty(order.Name)) { throw new InvalidOperationException("Order name cannot be empty."); } } } public class PublishAttribute : AspectAttribute { public override void BuildAspect(BuildAspectArgs args) { args.Enhancer.AddInitializer(this.PublishOrder, InitializerPosition.After); } private void PublishOrder(Order order, InitializationContext context) { Console.WriteLine($"Publishing order '{order.Name}'..."); // Simulate publishing logic } } [assembly: AspectOrder(AspectOrderDirection.RunTime, typeof(PublishAttribute), typeof(ValidateAttribute))] ``` -------------------------------- ### Registering live instances Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/aspects/advising/initializers.md Injects logic into instance constructors to register new instances in a live registry. Automatically removes instances from the registry upon garbage collection. ```csharp using Metalama.Framework.Aspects; using Metalama.Framework.Code; using Metalama.Framework.Diagnostics; namespace Metalama.Documentation.SampleCode.AspectFramework; [AttributeUsage( AttributeTargets.Class, AllowMultiple = false, Inherited = false )] public class RegisterInstanceAttribute : InstanceAspect { public override void BuildAspect( IAspectBuilder builder ) { builder.Advices.AddInitializer( InitializerKind.BeforeInstanceConstructor, "RegisterInstance" ); } [Template] public void RegisterInstance( object instance ) { LiveInstanceRegistry.Register( instance ); Console.WriteLine( "Instance registered: {0}", instance.GetType().Name ); } } public static class LiveInstanceRegistry { private static readonly ConditionalWeakTable _instances = new(); public static void Register( object instance ) { _instances.Add( instance, null ); Console.WriteLine( "Instance registered: {0}", instance.GetType().Name ); } // This method is called by the GC when an instance is finalized. public static void Unregister( object instance ) { Console.WriteLine( "Instance unregistered: {0}", instance.GetType().Name ); } } [RegisterInstance] public class MyService { public MyService() { Console.WriteLine( "MyService constructor called." ); } } ``` -------------------------------- ### Protected Interface Definition Source: https://github.com/metalama/metalama.documentation/blob/release/2026.1/content/conceptual/architecture/internal-only-implement.md Define an interface and apply the InternalOnlyImplementAttribute to prevent other assemblies from implementing it. Ensure the Metalama.Extensions.Architecture package is installed. ```csharp using Metalama.Extensions.Architecture.Aspects; namespace Metalama.Documentation.SampleCode.AspectFramework.Architecture; [InternalOnlyImplement] public interface IDependency { void DoSomething(); } ```