国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(完結(jié)篇)

這篇具有很好參考價(jià)值的文章主要介紹了聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(完結(jié)篇)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前言

書接上回,上回我們了解了 castle 代理的一些缺點(diǎn),本文將開始操作整合 Microsoft.Extension.Dependency和Castle,以讓默認(rèn)的容器可以支持?jǐn)r截器
我們將以進(jìn)階的形式逐步完善我們的封裝,以實(shí)現(xiàn)一個(gè)更方便易用、普適、高性能的基礎(chǔ)設(shè)施庫(kù)。

基礎(chǔ)版

還是先上代碼, 這是基礎(chǔ)版本我們要達(dá)成的目標(biāo),僅需定義一個(gè)特性即可完成攔截的目標(biāo)

/// <summary>
/// 
/// </summary>
public abstract class InterceptorBaseAttribute : Attribute, IInterceptor
{
    void IInterceptor.Intercept(IInvocation invocation)
    {
        var returnType = invocation.Method.ReturnType;
        var builder = AsyncMethodBuilder.TryCreate(returnType);
        if (builder != null)
        {
            var asyncInvocation = new AsyncInvocation(invocation);
            var stateMachine = new AsyncStateMachine(asyncInvocation, builder, task: InterceptAsync(asyncInvocation));
            builder.Start(stateMachine);
            invocation.ReturnValue = builder.Task();
        }
        else
        {
            Intercept(invocation);
        }
    }

    protected virtual void Intercept(IInvocation invocation) { }

    protected abstract ValueTask InterceptAsync(IAsyncInvocation invocation);
    ......
}

如上是我們定義的攔截器基類,我們想要達(dá)到的目標(biāo)是,只要繼承該基類,并覆寫InterceptAsync 方法即可實(shí)現(xiàn)具有特定功能的攔截類,而容器會(huì)自動(dòng)代理到該攔截類,實(shí)現(xiàn)攔截。
這里要感謝 https://github.com/stakx/DynamicProxy.AsyncInterceptor 的作者,該庫(kù)采用 MIT 的許可使用協(xié)議,我們可以直接參考使用。
接下來,是重頭戲,考慮到易用性,我們以 Microsoft.Extension.DependencyInjection 為基本庫(kù),實(shí)現(xiàn)一個(gè)擴(kuò)展類,用于實(shí)現(xiàn)攔截器功能。
代碼如下:

public static class CastleServiceCollectionExtensions
{
    public static IServiceCollection ConfigureCastleDynamicProxy(this IServiceCollection services)
    {
        services.TryAddSingleton<ProxyGenerator>(sp => new ProxyGenerator());
        //TODO:1.從IServiceCollection中獲取 方法定義InterceptorBaseAttribute特性子類的ServiceDescriptor

        //TODO:2.逐個(gè)處理,獲取每個(gè)ServiceDescriptor中的ServiceType,識(shí)別是具體類還是接口,然后獲取InterceptorBaseAttribute特性子類的實(shí)例
        //作為攔截器,借用proxyGenerator 去創(chuàng)建對(duì)應(yīng)的代理然后添加到IServiceCollection中

        //TODO:3 移除原始對(duì)應(yīng)的ServiceType注冊(cè)
        return services;
    }
}

在注釋中我們簡(jiǎn)單描述了該擴(kuò)展方法的實(shí)現(xiàn)過程,我們采用移花接木的方式替換掉原有ServiceType的注冊(cè),將代理對(duì)象注冊(cè)為ServiceType的實(shí)現(xiàn)即可。

第一步我們這么實(shí)現(xiàn)

var descriptors = services.Where(svc =>svc.ServiceType.GetMethods()
    .Any(i => i.GetCustomAttributes(false).Any(i => i.GetType().IsAssignableTo(typeof(InterceptorBaseAttribute))))).ToList();

第二步的核心是 ServiceDescriptor 中 三種生成場(chǎng)景的分開處理,至于是哪三種場(chǎng)景可以看下我的第一篇文章 https://www.cnblogs.com/gainorloss/p/17961153

  • descriptor.ImplementationType 有值:已知ServiceType和ImplementationType
    偽代碼如下
implementationFactory = sp =>
{
    var generator = sp.GetRequiredService<ProxyGenerator>();

    var interceptors = GetInterceptors(descriptor.ServiceType);//獲取攔截器 galoS@2024-1-12 14:47:47

    var proxy = descriptor.ServiceType.IsClass
    ? generator.CreateClassProxy(descriptor.ServiceType,  interceptors.ToArray())
    : generator.CreateInterfaceProxyWithoutTarget(descriptor.ServiceType, interceptors.ToArray());
    return proxy;
};
  • descriptor.ImplementationInstance 有值:已知ServiceType和 實(shí)現(xiàn)對(duì)象實(shí)例
implementationFactory = sp =>
{
    var generator = sp.GetRequiredService<ProxyGenerator>();
    var interceptors = GetInterceptors(descriptor.ServiceType, sp);//獲取攔截器 galoS@2024-1-12 14:47:47
    var proxy = descriptor.ServiceType.IsClass
    ? generator.CreateClassProxyWithTarget(descriptor.ServiceType, descriptor.ImplementationInstance, interceptors.ToArray())
    : generator.CreateInterfaceProxyWithTarget(descriptor.ServiceType, descriptor.ImplementationInstance, interceptors.ToArray());
    return proxy;
};
  • descriptor.ImplementationFactory 有值:已知ServiceType和 實(shí)現(xiàn)工廠方法
implementationFactory = sp =>
{
    var generator = sp.GetRequiredService<ProxyGenerator>();
    var interceptors = GetInterceptors(descriptor.ServiceType, sp);//獲取攔截器 galoS@2024-1-12 14:47:47
    var proxy = descriptor.ServiceType.IsClass
    ? generator.CreateClassProxyWithTarget(descriptor.ServiceType, descriptor.ImplementationInstance, interceptors.ToArray())
    : generator.CreateInterfaceProxyWithTarget(descriptor.ServiceType, descriptor.ImplementationInstance, interceptors.ToArray());
    return proxy;
};

可以看到 2,3比較雷同,因?yàn)槟玫?實(shí)例和通過委托傳入IServiceProvider拿到實(shí)例,其實(shí)結(jié)果是相似的,最終我們都使用工廠注入的形式 生成新的 ServiceDescriptor services.AddTransinet(descriptor.ServiceType, implementationFactory);
最后一步 移除即可
偽代碼如下
services.Remove(descriptor);

改造一下之前的代碼并測(cè)試

 var services = new ServiceCollection();
services.AddLogging();//此處添加日志服務(wù) 偽代碼 以便獲取ILogger<SampleService>
services.TryAddTransient<SampleService>();
services.TryAddTransient<ISampleService, SampleService>();
services.ConfigureCastleDynamicProxy();//一定要在最后,不然會(huì)有些服務(wù)無法代理到 2024-1-13 13:53:05
var sp = services.BuildServiceProvider();

var proxy = sp.GetRequiredService<SampleService>();
var name = await proxy.ShowAsync();

/// <summary>
/// 異常捕獲、日志記錄和耗時(shí)監(jiān)控 攔截器 2024-1-12 21:28:22
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CatchLoggingInterceptor : InterceptorBaseAttribute
{
   protected override async ValueTask InterceptAsync(IAsyncInvocation invocation)
   {
       //TODO:類注釋所寫的邏輯
       await Console.Out.WriteLineAsync("Interceptor  starting...");
       Console.WriteLine("Interceptor  starting...");
       await invocation.ProceedAsync();
       await Console.Out.WriteLineAsync("Interceptor  ended...");
   }
}

運(yùn)行如下
聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(完結(jié)篇)
,聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(完結(jié)篇)

可以看到攔截器這時(shí)候是異步方法,并且可以明顯看到注入被簡(jiǎn)化了。
大家可以考慮下為什么 services.ConfigureCastleDynamicProxy() 一定要在BuildServiceProvider()之前,其他注入之后

進(jìn)階版本

進(jìn)階 版本這里我們不再詳細(xì)描述,直接看源碼 https://gitee.com/gainorloss_259/microsoft-castle.git
主要解決的問題是castle 攔截器不支持 依賴ioc的服務(wù)
使用偽代碼如下

public class SampleService : ISampleService
{
   [CatchLoggingInterceptor]
   [Interceptor(typeof(LoggingInterceptor))]//第二種使用方式
   public virtual Task<string> ShowAsync()
   {
       Console.WriteLine(nameof(ShowAsync));
       return Task.FromResult(nameof(ShowAsync));
   }
}
//定義攔截器
internal class LoggingInterceptor : InterceptorBase
{
   private readonly ILogger<LoggingInterceptor> _logger;

   public LoggingInterceptor(ILogger<LoggingInterceptor> logger)
   {
       _logger = logger;
   }
   protected override async ValueTask InterceptAsync(IAsyncInvocation invocation)
   {
       await Console.Out.WriteLineAsync(nameof(LoggingInterceptor));
       await invocation.ProceedAsync();
   }
}

總結(jié)

以上 整合的核心方案及細(xì)節(jié)已經(jīng)介紹完畢了,接下來有時(shí)間的話可以出一篇對(duì)本整合做性能測(cè)試的文章;
AOP 是一個(gè)很強(qiáng)大的東西,我們基本已經(jīng)完成了一個(gè)比較普適、比較易用的aop底層整理。接下來我們可以做很多東西,比如 事務(wù)攔截器、冪等攔截器、重試攔截器、緩存攔截器等等
打好基礎(chǔ),后續(xù)可以自己去實(shí)現(xiàn)。
這里還有幾個(gè)問題 ,大家可以思考下

  1. 我們?nèi)绾文苷蟽煞N攔截器 既可以傳一些常量又不影響我們的服務(wù)注入攔截器
  2. 攔截器是否可以再套用攔截器
  3. 假設(shè)我們?cè)偃罩緮r截器上打了日志攔截器 會(huì)怎么樣

這些都是一些比較有意思的問題,相信這些問題的思考會(huì)讓大家對(duì)動(dòng)態(tài)代理的理解更深,并可以靈活的將其用到自己的項(xiàng)目中。

源碼及聲明

當(dāng)前示例代碼已傳至 https://gitee.com/gainorloss_259/microsoft-castle.git
如轉(zhuǎn)載請(qǐng)注明出處,謝謝!文章來源地址http://www.zghlxwxcb.cn/news/detail-786374.html

到了這里,關(guān)于聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(完結(jié)篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 聊一聊synchronized

    在 Java 中, synchronized 可以用于實(shí)現(xiàn)線程同步,有以下幾種常見的使用方式: 修飾代碼塊:將 synchronized 放在代碼塊的前面, 例如: 在這種方式下,會(huì)為給定的對(duì)象 obj 獲取鎖,在代碼塊執(zhí)行期間,只有持有該鎖的線程才能進(jìn)入代碼塊執(zhí)行。 修飾方法:將 sync

    2024年01月22日
    瀏覽(27)
  • 聊一聊AIGC

    聊一聊AIGC

    “UGC不存在了”——借鑒自《三體》 ChatGPT 的橫空出世將一個(gè)全新的概念推上風(fēng)口——AIGC( AI Generated Content)。 GC即創(chuàng)作內(nèi)容(Generated Content),和傳統(tǒng)的UGC、PGC,OGC不同的是,AIGC的創(chuàng)作主體由人變成了人工智能。 xGC PGC:Professionally Generated Content,專業(yè)生產(chǎn)內(nèi)容 UGC:User G

    2024年02月10日
    瀏覽(23)
  • 聊一聊模板方法模式

    聊一聊模板方法模式

    統(tǒng)一抽取,制定規(guī)范; 模板方法模式,又叫模板模式,屬于23種設(shè)計(jì)模式中的 行為型模式 。在抽象類中公開定義了執(zhí)行的方法,子類可以按需重寫其方法,但是要以抽象類中定義的方式調(diào)用方法。總結(jié)起來就是: 定義一個(gè)操作的算法結(jié)構(gòu),而將一些步驟延遲到子類中。在不

    2024年02月04日
    瀏覽(26)
  • 聊一聊適配器模式

    聊一聊適配器模式

    接口不能用?行,我?guī)湍氵m配 適配器模式(Adapter),是23種設(shè)計(jì)模式中的 結(jié)構(gòu)型模式 之一;它就像我們電腦上接口不夠時(shí),需要用到的拓展塢,起到轉(zhuǎn)接的作用。它可以將新的功能和原先的功能連接起來,使由于需求變動(dòng)導(dǎo)致不能用的功能,重新利用起來。 上圖的Mac上,只

    2024年02月04日
    瀏覽(25)
  • 聊一聊Vue和Ts

    1 前言 Vue3 已經(jīng)正式發(fā)布了一段時(shí)間了,各種生態(tài)已經(jīng)成熟。最近使用 taro+vue3 重構(gòu)冷鏈的小程序,經(jīng)過了一段時(shí)間的開發(fā)和使用,有了一些自己的思考。 總的來說,Vue3 無論是在底層原理還是在實(shí)際開發(fā)過程中,都有了很大的進(jìn)步。 從源碼層面來說,使用 Proxy 代替 Object.d

    2023年04月08日
    瀏覽(26)
  • 聊一聊mysql中的間隙鎖

    聊一聊mysql中的間隙鎖

    間隙鎖在mysql中經(jīng)常使用到,今天就聊一聊mysql的間隙鎖的內(nèi)容。 間隙鎖是為了解決幻讀的問題,并且在當(dāng)前讀的場(chǎng)景下解決的。 當(dāng)前讀包含:update,delete,insert,select…lock in share mode,select…for update 一基本概念 1、行鎖:給某一行進(jìn)行加鎖 2、間隙鎖:兩個(gè)值之間的間隙,為解

    2024年02月12日
    瀏覽(22)
  • 聊一聊Java抽象同步隊(duì)列AQS

    聊一聊Java抽象同步隊(duì)列AQS

    AQS是鎖的底層支持 由該圖可以看到,AQS是一個(gè)FIFO的雙向隊(duì)列,其內(nèi)部通過節(jié)點(diǎn)head和tail記錄隊(duì)首和隊(duì)尾元素,隊(duì)列元素的類型為Node。其中Node中的thread變量用來存放進(jìn)入AQS隊(duì)列里面的線程;Node節(jié)點(diǎn)內(nèi)部的SHARED用來標(biāo)記該線程是獲取共享資源時(shí)被阻塞掛起后放入AQS隊(duì)列的,EX

    2024年02月16日
    瀏覽(33)
  • 聊一聊nginx中KeepAlive的設(shè)置

    聊一聊nginx中KeepAlive的設(shè)置

    之前工作中遇到一個(gè)KeepAlive的問題,現(xiàn)在把它記錄下來,場(chǎng)景是這樣的: 從上圖可以看出,用戶通過Client訪問的是LVS的VIP, VIP后端掛載的RealServer是Nginx服務(wù)器。 Client可以是瀏覽器也可以是一個(gè)客戶端程序。一般情況下, 這種架構(gòu)不會(huì)出現(xiàn)問題,但是如果Client端把請(qǐng)求發(fā)送給

    2024年02月01日
    瀏覽(27)
  • 聊一聊醫(yī)療器械的可用性

    很抱歉由于各種因素這個(gè)號(hào)拖更了好久了,最近呢也有幾個(gè)公眾號(hào)做的挺好的,比如包總的 MD SRE 、丁總的 醫(yī)械安全 、 餑餑糕的叨逼叨 ,而且更新也都比較頻繁,大家可以 關(guān)注 一下; 好久沒登錄,當(dāng)我上來看到已經(jīng)有 5000多 的關(guān)注者,說實(shí)話,有 感動(dòng) ,有 自豪 ,也有

    2024年02月07日
    瀏覽(24)
  • 聊一聊 .NET高級(jí)調(diào)試 內(nèi)核模式堆泄露

    聊一聊 .NET高級(jí)調(diào)試 內(nèi)核模式堆泄露

    前幾天有位朋友找到我,說他的機(jī)器內(nèi)存在不斷的上漲,但在任務(wù)管理器中查不出是哪個(gè)進(jìn)程吃的內(nèi)存,特別奇怪,截圖如下: 在我的分析旅程中都是用戶態(tài)模式的內(nèi)存泄漏,像上圖中的異常征兆已經(jīng)明確告訴你了,不是用戶態(tài)程序吃的內(nèi)存,那就是內(nèi)核態(tài)程序吃的,比如:

    2024年02月04日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包