您的位置:首頁 > 軟件教程 > 教程 > c# 12 實驗特性Interceptor 是什么?

c# 12 實驗特性Interceptor 是什么?

來源:好特整理 | 時間:2024-08-07 09:48:28 | 閱讀:63 |  標簽: T 2 一個 C in 實驗 inter   | 分享到:

一直有很多轉載dotnet對Interceptor說明文檔的,但鮮有說明Interceptor如何使用的,這里寫一篇簡單示例來展示一下 c# 12 實驗特性Interceptor 是什么? 官方解釋如下(其實簡單說就是語言特性中內置的靜態(tài)編織方式的aop功能,不同于其他il修改代碼的方式,使用上得結

在dotnet社區(qū)中,雖然有很多關于Interceptor的轉載說明文檔,但很少有關于Interceptor如何使用的詳細說明。本文將通過一個簡單示例來展示Interceptor的使用方法。

Interceptor是一種內置的靜態(tài)編織方式的aop功能,與其他il修改代碼的方式不同。它可以在編譯時以聲明方式將對可攔截方法的調用替換為對其自身的調用。通過讓攔截器聲明所攔截調用的源位置,可以進行這種替換。攔截器可以向編譯中(例如在源生成器中)添加新代碼,從而提供更改現(xiàn)有代碼語義的有限能力。

在源生成器中使用攔截器修改現(xiàn)有編譯的代碼,而非向其中添加代碼。源生成器將對可攔截方法的調用替換為對攔截器方法的調用。

如果你有興趣嘗試攔截器,可以閱讀功能規(guī)范來了解詳細信息。如果使用該功能,請確保隨時了解此實驗功能的功能規(guī)范中的任何更改。最終確定功能后將在微軟文檔站點上添加更多指導。

示例

這里我們用一個簡單的 static method 作為我們改寫方法內容的目標。

public static partial class DBExtensions
{
  public static string TestInterceptor(object o)
  {
      return o.GetType().ToString();
  }
}

這樣的靜態(tài)方法,我們假設改寫的目標為返回o參數的其中一個string類型的屬性值。

所以應該可以通過如下的 UT 方法:

[Fact]
public void CallNoError()
{
    Assert.Equal("sss", DBExtensions.TestInterceptor(new { A = "sss", C= "ddd" }));
}

如何實現(xiàn)

第一步 建立類庫

建立一個 netstandard2.0 的類庫并設置如下:


  
    netstandard2.0
    preview
    true
    
    false
    
  
  
    
    
  
  
    
    
  

第二步 設置 UT 項目開啟 Interceptor 功能

Generated 目錄生成代碼文件其實是非必須的,但是為了方便大家看到 source generater 生成的代碼文件內容,對于我們初次嘗試source generater很有幫助。


  
    net8.0
    enable
    enable
    false
    true
    Generated
    $(InterceptorsPreviewNamespaces);Test.AOT
  
  
    
  
  
    
  
  
    
  
  
    
    
  

第三步 實現(xiàn) InterceptorGenerator

[Generator(LanguageNames.CSharp)]
public class InterceptorGenerator : IIncrementalGenerator
{
}

這里的 IIncrementalGenerator 為source generater更強設計的一代接口,有更強的性能和更方便的能力。接著我們來實現(xiàn)接口。

[Generator(LanguageNames.CSharp)]
public class InterceptorGenerator : IIncrementalGenerator
{
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            var nodes = context.SyntaxProvider.CreateSyntaxProvider(FilterFunc, TransformFunc).Where(x => x is not null).Select((x, _) => x!);
            var combined = context.CompilationProvider.Combine(nodes.Collect());
            context.RegisterImplementationSourceOutput(combined, Generate);
        }
}

接著我們來實現(xiàn) FilterFunc 。

private bool FilterFunc(SyntaxNode node, CancellationToken token)
{
    if (node is InvocationExpressionSyntax ie && ie.ChildNodes().FirstOrDefault() is MemberAccessExpressionSyntax ma)
    {
        return ma.Name.ToString().StartsWith("TestInterceptor");
    }
    return false;
}

接著我們來實現(xiàn) TransformFunc

private TestData TransformFunc(GeneratorSyntaxContext ctx, CancellationToken token)
{
    // 實現(xiàn)代碼
}

接著我們來實現(xiàn) Generate 。

private void Generate(SourceProductionContext ctx, (Compilation Left, ImmutableArray Right) state)
{
    // 實現(xiàn)代碼
}

最后一步 編譯試試

如果我們編譯程序,就會看見生成了這樣的文件代碼。


// 生成的代碼

如果運行ut,結果也正確,debug逐行調試也可看到斷點能進入我們生成的代碼文件中。

小編推薦閱讀

好特網發(fā)布此文僅為傳遞信息,不代表好特網認同期限觀點或證實其描述。

相關視頻攻略

更多

掃二維碼進入好特網手機版本!

掃二維碼進入好特網微信公眾號!

本站所有軟件,都由網友上傳,如有侵犯你的版權,請發(fā)郵件[email protected]

湘ICP備2022002427號-10 湘公網安備:43070202000427號© 2013~2025 haote.com 好特網