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

.net core IOC 容器實現(xiàn)(四) -- CallSiteRuntimeResolver

這篇具有很好參考價值的文章主要介紹了.net core IOC 容器實現(xiàn)(四) -- CallSiteRuntimeResolver。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

上一節(jié)聊了一下 CallSite 是怎樣生成的,這一節(jié)我們來看一下 CallSite 是如何使用的。

入口

先讓我們來回顧一下 CreateServiceAccessor 這個方法。

private Func<ServiceProviderEngineScope, object?> CreateServiceAccessor(Type serviceType)        
{
    //通過 服務類型 獲取 callSite           
    ServiceCallSite? callSite = CallSiteFactory.GetCallSite(serviceType, new CallSiteChain());            
    if (callSite != null)           
    {                           
        if (callSite.Cache.Location == CallSiteResultCacheLocation.Root)                
        {                
            //直接解析    
            object? value = CallSiteRuntimeResolver.Instance.Resolve(callSite, Root);                                  
        }                       
        return _engine.RealizeService(callSite);            
    }
}

這段代碼跟 CallSite 有關的一共有三個地方,分別是 GetCallSiteResolve(callSite,Root)以及 _engine.RealizeService。其中 GetCallSite 是用來生成 CallSite 的(也就是上一節(jié)的主要內容),而剩下的兩個則是對于 CallSite 的使用,也是這一節(jié)的主要內容。

RealizeService

我們先看一下 _engine.RealizeService 方法。

public override Func<ServiceProviderEngineScope, object?> RealizeService(ServiceCallSite callSite)
{                      
    return scope =>            
    {                
        var result = CallSiteRuntimeResolver.Instance.Resolve(callSite, scope);                       
        return result;            
    };        
}

我們可以發(fā)現(xiàn)最終調用的還是 CallSiteRuntimeResolver.Instance.Resolve 這個方法,所以其實歸根結底對 CallSite 的調用其實最終就是一個地方,也就是這個 Resolve 方法。

CallSiteRuntimeResolver.Resolve

public object? Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
{
    // 如果在 root scope 范圍里已經(jīng)有緩存了,直接返回
    if (scope.IsRootScope && callSite.Value is object cached)
    {
        return cached;
    }
    //調用 VisitCallSite 進行解析
    return VisitCallSite(callSite, new RuntimeResolverContext
    {
        Scope = scope
    });
}

VisitCallSite

protected virtual TResult VisitCallSite(ServiceCallSite callSite, TArgument argument)
{
    switch (callSite.Cache.Location)
    {
        case CallSiteResultCacheLocation.Root:
            return VisitRootCache(callSite, argument);
        case CallSiteResultCacheLocation.Scope:
            return VisitScopeCache(callSite, argument);
        case CallSiteResultCacheLocation.Dispose:
            return VisitDisposeCache(callSite, argument);
        case CallSiteResultCacheLocation.None:
            return VisitNoCache(callSite, argument);
        default:
            throw new ArgumentOutOfRangeException();
    }
}

VisitCallSite 會根據(jù) Location 進行分支處理,Location 是 CallSite 里的一個屬性。其中 Root 對應 Singleton,Scope 對應 Scope 生命周期,Dispose 對應 Trasient,None可以先將其理解為Singleton。

VisitRootCache(Single)

protected override object? VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
{
    // Singleton 懶加載 如果有 value 直接返回          
    if (callSite.Value is object value)
    {
        // Value already calculated, return it directly
        return value;
    }

    var lockType = RuntimeResolverLock.Root;
    //在 root 范圍進行解析
    ServiceProviderEngineScope serviceProviderEngine = context.Scope.RootProvider.Root;
    // 鎖住 callSite 防止重復生成value

    lock (callSite)
    {
        // Lock the callsite and check if another thread already cached the value
        // 可能其他地方已經(jīng)生成了,在獲取一下看看        
        if (callSite.Value is object callSiteValue)
        {
            return callSiteValue;
        }
        //最終依舊是調用了 VisitCallSiteMain 方法

        object? resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
        {
            Scope = serviceProviderEngine,
            AcquiredLocks = context.AcquiredLocks | lockType
        });
        serviceProviderEngine.CaptureDisposable(resolved);
        //進行緩存
        callSite.Value = resolved;
        return resolved;
    }
}

VisitScopeCache(Scope)

// Check if we are in the situation where scoped service was promoted to singleton
// and we need to lock the root
// Scope 依賴 Singleton
return context.Scope.IsRootScope ?
    VisitRootCache(callSite, context) :
    VisitCache(callSite, context, context.Scope, RuntimeResolverLock.Scope);
private object? VisitCache(
    ServiceCallSite callSite, 
    RuntimeResolverContext context, 
    ServiceProviderEngineScope serviceProviderEngine, 
    RuntimeResolverLock lockType)
{
    bool lockTaken = false;
    object sync = serviceProviderEngine.Sync;
    // Dictionary<ServiceCacheKey, object?> ResolvedServices { get; } 緩存
    Dictionary<ServiceCacheKey, object?> resolvedServices = serviceProviderEngine.ResolvedServices;
    // Taking locks only once allows us to fork resolution process
    // on another thread without causing the deadlock because we
    // always know that we are going to wait the other thread to finish before
    // releasing the lock
    // 鎖住 sync 對象
    if ((context.AcquiredLocks & lockType) == 0)
    {
        Monitor.Enter(sync, ref lockTaken);
    }
    try
    {
        //獲取鎖之后
        // Note: This method has already taken lock by the caller for resolution and access synchronization.
        // For scoped: takes a dictionary as both a resolution lock and a dictionary access lock.
        //先訪問緩存
        if (resolvedServices.TryGetValue(callSite.Cache.Key, out object? resolved))
        {
            return resolved;
        }
        //解析
        resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
        {
            Scope = serviceProviderEngine,
            AcquiredLocks = context.AcquiredLocks | lockType
        });
        //緩存需要釋放的實例
        serviceProviderEngine.CaptureDisposable(resolved);
        //放入緩存
        resolvedServices.Add(callSite.Cache.Key, resolved);
        return resolved;
    }
    finally
    {
        //解鎖
        if (lockTaken)
        {
            Monitor.Exit(sync);
        }
    }
}

VisitDisposeCache(Transient)

protected override object? VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)        
{    
    //解析        
    var instance=VisitCallSiteMain(transientCallSite, context);
    return context.Scope.CaptureDisposable(instance);        
}

VisitNoCache(None)

protected virtual TResult VisitNoCache(ServiceCallSite callSite, TArgument argument)
{
    return VisitCallSiteMain(callSite, argument);
}

VisitCallSiteMain

觀察以上方法,我們可以發(fā)現(xiàn)無論是 VisitRootCache還是VisitScopeCache 等等,最終都是調用 VisitCallSiteMain 這個方法來生成的實例。

protected virtual TResult VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
{
    //callSite.kind 是只讀屬性 ,在 GetCallSite 時確定,根據(jù) CallSite 類型確定(例 ConstantCallSite)
    switch (callSite.Kind)
    {
        case CallSiteKind.Factory:
            return VisitFactory((FactoryCallSite)callSite, argument);
        case CallSiteKind.IEnumerable:
            return VisitIEnumerable((IEnumerableCallSite)callSite, argument);
        case CallSiteKind.Constructor:
            return VisitConstructor((ConstructorCallSite)callSite, argument);
        case CallSiteKind.Constant:
            return VisitConstant((ConstantCallSite)callSite, argument);
        case CallSiteKind.ServiceProvider:
            return VisitServiceProvider((ServiceProviderCallSite)callSite, argument);
        default:
            throw new NotSupportedException(SR.Format(SR.CallSiteTypeNotSupported, callSite.GetType()));
    }
}

VisitConstructor

其中比較復雜的就是這個 VisitConstructor 方法,通過反射來構造實例,主要思路是拿到實例類型的構造函數(shù),然后通過遞歸(調用VisitCallSite(見本文最上方))準備構造函數(shù)所需要的參數(shù),最后調用 invoke 來生成實例。

protected override object VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
{
    object?[] parameterValues;
    //獲取構造需要使用的參數(shù)
    //無參
    if (constructorCallSite.ParameterCallSites.Length == 0)
    {
        parameterValues = Array.Empty<object>();
    }
    //有參
    else
    {
        parameterValues = new object?[constructorCallSite.ParameterCallSites.Length];
        for (int index = 0; index < parameterValues.Length; index++)
        {
            //遞歸解析 VisitCallSite 見上文
            parameterValues[index] = VisitCallSite(constructorCallSite.ParameterCallSites[index], context);
        }
    }
#if NETFRAMEWORK || NETSTANDARD2_0
            try
            {
                return constructorCallSite.ConstructorInfo.Invoke(parameterValues);
            }
            catch (Exception ex) when (ex.InnerException != null)
            {
                ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                // The above line will always throw, but the compiler requires we throw explicitly.
                throw;
            }
#else
    return constructorCallSite.ConstructorInfo.Invoke(BindingFlags.DoNotWrapExceptions, binder: null, 
                                                        parameters: parameterValues, culture: null);
#endif
}

VisitFactory

protected override object VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
{
    //調用  Factory(Func<IServiceProvider, object> Factory) 委托(委托由開發(fā)者實現(xiàn))
    return factoryCallSite.Factory(context.Scope);
}

VisitIEnumerable

protected override object VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
{
    //創(chuàng)建枚舉類型的數(shù)組
    var array = Array.CreateInstance(
        enumerableCallSite.ItemType,
        enumerableCallSite.ServiceCallSites.Length);                            

    //給數(shù)組填充值
    for (int index = 0; index < enumerableCallSite.ServiceCallSites.Length; index++)
    {
        object? value = VisitCallSite(enumerableCallSite.ServiceCallSites[index], context);
        array.SetValue(value, index);
    }
    return array;
}

VisitConstant

protected override object? VisitConstant(ConstantCallSite constantCallSite, RuntimeResolverContext context)        
{            
    //直接返回保存的實例
    return constantCallSite.DefaultValue;        
}

VisitServiceProvider

protected override object VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, RuntimeResolverContext context)        
{            
    return context.Scope;        
}

總結

先根據(jù)實例的生命周期進行分支判斷,接下來根據(jù)服務的生成方式進行分支判斷。
.net core IOC 容器實現(xiàn)(四) -- CallSiteRuntimeResolver文章來源地址http://www.zghlxwxcb.cn/news/detail-600637.html

到了這里,關于.net core IOC 容器實現(xiàn)(四) -- CallSiteRuntimeResolver的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • .NET6.0實現(xiàn)IOC容器

    IOC 的作用這里省略…只對如何使用進行說明。 這里使用 .NET6.0 WebAPI 應用 下面是在 program 類中的代碼 通過在 Controller 的構造函數(shù)中注入 IAuthService 啟動后,通過 swagger 發(fā)起請求,驗證接口。 基本 IOC容器 流程已實現(xiàn)。但是這樣存在一個弊端,每個接口和實現(xiàn)都要在 program 中手

    2024年02月10日
    瀏覽(24)
  • .net core di ioc

    .net core di ioc

    (Dependency Injection,DI)依賴注入,又稱依賴關系注入,是一種軟件設計模式,也是依賴倒置原則的一種體現(xiàn)。 依賴倒置原則的含義如下 上層模塊不依賴下層模塊。二者都依賴抽象 抽象不依賴細節(jié) 細節(jié)依賴抽象 依賴注入原則有別于傳統(tǒng)的通過new直接依賴下層模塊的形式,

    2024年02月22日
    瀏覽(31)
  • asp.net core6 webapi 使用反射批量注入接口層和實現(xiàn)接口層的接口的類到ioc中

    IBLL接口層類庫 BLL實現(xiàn)接口層類庫 program中利用反射批量注入 在控制器中使用構造函數(shù)傳參就可以調用已經(jīng)注冊的所有是是實現(xiàn)接口的類了的實列了

    2024年02月13日
    瀏覽(24)
  • 【.NET6+WPF】WPF使用prism框架+Unity IOC容器實現(xiàn)MVVM雙向綁定和依賴注入

    【.NET6+WPF】WPF使用prism框架+Unity IOC容器實現(xiàn)MVVM雙向綁定和依賴注入

    前言:在C/S架構上,WPF無疑已經(jīng)是“桌面一霸”了。在.NET生態(tài)環(huán)境中,很多小伙伴還在使用Winform開發(fā)C/S架構的桌面應用。但是WPF也有很多年的歷史了,并且基于MVVM的開發(fā)模式,受到了很多開發(fā)者的喜愛。 并且隨著工業(yè)化的進展,以及幾年前微軟對.NET平臺的開源,國內大多

    2024年02月06日
    瀏覽(28)
  • .Net Core后端架構實戰(zhàn)【3-介入IOC控制反轉】

    .Net Core后端架構實戰(zhàn)【3-介入IOC控制反轉】

    摘要:基于.NET Core 7.0WebApi后端架構實戰(zhàn)【2-介入IOC控制反轉】??2023/04/09, ASP.NET Core 7.0, VS2022 Dependency Injection,何為依賴注入?由容器動態(tài)的將對象依賴的資源注入到對象之中。假設容器在構造對象A時,對象A的構造依賴對象B、對象C、對象D這些參數(shù),容器會將這些依賴關系自

    2024年02月07日
    瀏覽(22)
  • .NET開源IOC內置容器,生命周期管理與Autofac擴展

    .NET開源IOC內置容器,生命周期管理與Autofac擴展

    大家好,我是行不更名,坐不改姓的宋曉剛,下面將帶領大家從基礎小白到高階的.NET的IOC容器依賴與注入,以及IOC內置容器和生命周期,Autofac的學習,跟上我的步伐進入C#的世界。 微信:15319589104 QQ: 2981345658 文章內容: .NET依賴注入容器的生命周期管理,瞬時生命周期(

    2024年01月21日
    瀏覽(18)
  • 如何在ASP.NET Core應用中實現(xiàn)與第三方IoC/DI框架的整合?

    如何在ASP.NET Core應用中實現(xiàn)與第三方IoC/DI框架的整合?

    我們知道整個ASP.NET Core建立在以ServiceCollection/ServiceProvider為核心的DI框架上,它甚至提供了擴展點使我們可以與第三方DI框架進行整合。對此比較了解的讀者朋友應該很清楚,針對第三方DI框架的整合可以通過在定義Startup類型的ConfigureServices方法返回一個ServiceProvider來實現(xiàn)。但

    2024年02月09日
    瀏覽(32)
  • .net下優(yōu)秀的IOC容器框架Autofac的使用方法,實例解析

    .net下優(yōu)秀的IOC容器框架Autofac的使用方法,實例解析

    Autofac是一個功能強大的依賴注入容器,它提供了一種簡單和靈活的方式來管理對象之間的依賴關系。下面是Autofac的一些優(yōu)點: 簡單易用:Autofac提供了一種直觀和簡潔的方式來注冊和解析依賴項。它的API設計得非常易于理解和使用,使得開發(fā)人員可以輕松地配置和管理依賴關

    2024年02月05日
    瀏覽(23)
  • 【ASP.NET Core 基礎知識】--最佳實踐和進階主題--微服務和容器化

    Tip:想要了解并學習微服務和容器化的知識,請?zhí)D到《Docker極簡教程》 一、微服務概述 1.1 什么是微服務? 微服務(Microservices)是一種軟件架構風格,其中軟件系統(tǒng)被劃分為一組小型、自治的服務單元,這些服務單元圍繞著業(yè)務能力進行組織,并通過輕量級的通信機制相

    2024年02月19日
    瀏覽(87)
  • spring6-實現(xiàn)簡易版IOC容器

    我們都知道,Spring框架的IOC是基于Java反射機制實現(xiàn)的,下面我們先回顧一下java反射。 1、回顧Java反射 Java 反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調

    2024年02月08日
    瀏覽(20)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領取紅包

二維碼2

領紅包