Interceptors allow a method to declare it should be used in place of a specific call elsewhere in the project's source code by identifying that call's location with the InterceptsLocationAttribute.
This is useful for code generation scenarios where code-generated methods could add new functionality but could not replace or remove existing code unless that code was specifically written in a way to permit replacement or removal.
Code
csharp
// User-written "Program.cs"
partial class Program
{
public void PerformOperation()
{
Initialize();
}
public void Initialize()
{
// ...
}
}
// Code-generated "Program.generated.cs"
static class ProgramInterceptors
{
// The generator gets the location of the Initialize() call above
// from SemanticModel.GetInterceptableLocation()
[InterceptsLocation(version: 1, data: "...")]
public static void SpecialInitialize(this Program program)
{
// ...
}
}csharp
// User-written "Program.cs"
partial class Program
{
private Action? initializer;
partial void PerformOperationStartHook();
public void PerformOperation()
{
initializer = Initialize;
PerformOperationStartHook();
initializer();
}
public void Initialize()
{
// ...
}
}
// Code-generated "Program.generated.cs"
partial class Program
{
partial void PerformOperationStartHook()
{
initializer = SpecialInitialize;
}
public void SpecialInitialize()
{
// ...
}
}Notes
- The interceptor must be a
staticmethod whose signature matches the intercepted call. For instance methods, the first parameter is the receiver and is annotated withthisjust like an extension method C# 3.0 - Projects opt in by listing the interceptor's namespace in the
<InterceptorsNamespaces>MSBuild property (<InterceptorsPreviewNamespaces>in the .NET 8 SDK, still accepted as an alias) InterceptsLocationAttributeis declared by the generator itself, typically as a file-local type C# 11.0- The location
datais an opaque encoded string produced by the compiler API rather than written by hand; the original design used a file path, line and column instead