您的位置:首頁(yè) > 軟件教程 > 教程 > c# 12 實(shí)驗(yàn)特性Interceptor 是什么?

c# 12 實(shí)驗(yàn)特性Interceptor 是什么?

來源:好特整理 | 時(shí)間:2024-08-07 09:48:28 | 閱讀:144 |  標(biāo)簽: T 2 一個(gè) C in 實(shí)驗(yàn) inter   | 分享到:

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

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

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

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

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

示例

這里我們用一個(gè)簡(jiǎn)單的 static method 作為我們改寫方法內(nèi)容的目標(biāo)。

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

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

所以應(yīng)該可以通過如下的 UT 方法:

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

如何實(shí)現(xiàn)

第一步 建立類庫(kù)

建立一個(gè) netstandard2.0 的類庫(kù)并設(shè)置如下:


  
    netstandard2.0
    preview
    true
    
    false
    
  
  
    
    
  
  
    
    
  

第二步 設(shè)置 UT 項(xiàng)目開啟 Interceptor 功能

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


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

第三步 實(shí)現(xiàn) InterceptorGenerator

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

這里的 IIncrementalGenerator 為source generater更強(qiáng)設(shè)計(jì)的一代接口,有更強(qiáng)的性能和更方便的能力。接著我們來實(shí)現(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);
        }
}

接著我們來實(shí)現(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;
}

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

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

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

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

最后一步 編譯試試

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


// 生成的代碼

如果運(yùn)行ut,結(jié)果也正確,debug逐行調(diào)試也可看到斷點(diǎn)能進(jìn)入我們生成的代碼文件中。

小編推薦閱讀

好特網(wǎng)發(fā)布此文僅為傳遞信息,不代表好特網(wǎng)認(rèn)同期限觀點(diǎn)或證實(shí)其描述。

相關(guān)視頻攻略

更多

掃二維碼進(jìn)入好特網(wǎng)手機(jī)版本!

掃二維碼進(jìn)入好特網(wǎng)微信公眾號(hào)!

本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]

湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)