C# 12 攔截器 Interceptors

chester·chen發表於2024-03-20

攔截器Interceptors是一種可以在編譯時以宣告方式替換原有應用的方法。

這種替換是透過讓Interceptors宣告它攔截的呼叫的源位置來實現的。

您可以使用攔截器作為源生成器的一部分進行修改,而不是向現有源編譯新增程式碼。

演示

使用 .NET 8 建立一個控制檯應用程式。並在PropertyGroup中新增以下配置.。需要將其中WebApplication6替換為自己的名稱空間。

<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);WebApplication6</InterceptorsPreviewNamespaces>

然後在單獨的檔案中建立InterceptsLocationAttribute。其名稱空間必須是System.Runtime.CompilerServices,而不是應用程式的名稱空間。

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public sealed class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute
    {
    }
}

該屬性包含三個引數。

  • filePath是您要攔截的檔案的路徑。
  • line是您要攔截的程式碼行。
  • character是您要攔截的程式碼字元位置。

接著來建立一個具有三種方法的類,模擬新增/查詢使用者作為示例:

public class GetUserService
{
    // This method will not be intercepted;
    public void GetUserName()
    {
        Console.WriteLine("GetUserName");
    }

    // This method will be intercepted;
    public void AddUser()
    {
        Console.WriteLine("AddUser");
    }

    // This method will not be intercepted;
    public void DeleteUser()
    {
        Console.WriteLine("DeleteUser");
    }
}

在 Program.cs 檔案中,我建立了此類的一個例項,並建立了對這三個方法中每一個的呼叫。輸出如下所示:

var userService = new GetUserService();

userService.GetUserName();
userService.AddUser();
userService.DeleteUser();

現在讓我們建立攔截類。該類必須遵循以下規則:

  • 一定是一個static類。
  • 必須是我們要攔截的類的擴充套件方法。
  • 必須具有該InterceptsLocation屬性,其中包含我們要攔截的檔案路徑的值以及行號和字元號。

using System.Runtime.CompilerServices;

namespace WebApplication6
{
    public static class InterceptUserService
    {
        [InterceptsLocation(
    filePath: @"D:\demo\test\ConsoleApp1\WebApplication6\Program.cs",
    line: 14,
    character: 25)]
        public static void InterceptMethodAddUser(this GetUserService example)
        {
            Console.WriteLine("Interceptor is here!");
        }
    }
}

在此示例中,將攔截AddUser方法,並且將執行InterceptMethodAddUser方法,而不是執行方法AddUser。

filePath可以按以下方式獲取

行號和字元號可以按以下方式獲取

現在執行程式碼,方法AddUser將被攔截,並且不會被執行,而是實際執行攔截器方法,以下是輸出:

相關文章