溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ASP.NET?Core依賴注入實(shí)例分析

發(fā)布時(shí)間:2022-04-13 13:40:33 來(lái)源:億速云 閱讀:314 作者:iii 欄目:開(kāi)發(fā)技術(shù)

今天小編給大家分享一下ASP.NET Core依賴注入實(shí)例分析的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

ASP.NET Core的底層設(shè)計(jì)支持和使用依賴注入。ASP.NET Core 應(yīng)用程序可以利用內(nèi)置的框架服務(wù)將服務(wù)注入到啟動(dòng)類的方法中,并且應(yīng)用程序服務(wù)也可以配置注入。由ASP.NET Core 提供的默認(rèn)服務(wù)容器提供了最小功能集,并不是取代其他容器。

1.淺談依賴注入

依賴注入(Dependency injection,DI)是一種實(shí)現(xiàn)對(duì)象和依賴者之間松耦合的技術(shù),將類用來(lái)執(zhí)行其操作的這些對(duì)象以注入的方式提供給該類,而不是直接實(shí)例化依賴項(xiàng)或者使用靜態(tài)引用。一般情況,類會(huì)通過(guò)構(gòu)造函數(shù)聲明器2依賴關(guān)系,允許他們遵循顯示依賴原則。這種方法稱為“構(gòu)造函數(shù)注入”。

當(dāng)類的設(shè)計(jì)使用DI思想時(shí),他們的耦合更加松散,因?yàn)樗麄儧](méi)有對(duì)他們的合作者直接硬編碼的依賴。這遵循“依賴倒置原則”,其中指出,高層模塊不應(yīng)該依賴于底層模塊:兩者都依賴于抽象。

類要求在他們構(gòu)造時(shí)向其提供抽象(通常是接口),而不是引用特定的實(shí)現(xiàn)。提取接口的依賴關(guān)系和提供接口的實(shí)現(xiàn)作為參數(shù)也是“策略設(shè)計(jì)模式”的一個(gè)示例。

當(dāng)一個(gè)類被用來(lái)創(chuàng)建類及其相關(guān)的依賴關(guān)系時(shí),這個(gè)成為容器(containers),或者稱為控制反轉(zhuǎn)(Inversion of Control, IoC)容器,或者依賴注入容器。容器本質(zhì)上是一個(gè)工廠,負(fù)責(zé)提供向它請(qǐng)求的類型的實(shí)例。如果一個(gè)給定類型聲明它具有依賴關(guān)系,并且容器已經(jīng)被配置為其提供依賴關(guān)系,那么它將把創(chuàng)建依賴關(guān)系作為創(chuàng)建請(qǐng)求實(shí)例的一部分。除了創(chuàng)建對(duì)象的依賴關(guān)系外,容器通常還會(huì)管理應(yīng)用程序中對(duì)象的生命周期。

ASP.NET Core 包含一個(gè)默認(rèn)支持構(gòu)造函數(shù)注入的簡(jiǎn)單內(nèi)置容器,ASP.NET 的容器指的是它管理的類型services,可以在Startup類的ConfigureServices方法中配置內(nèi)置容器的服務(wù)。

2. 使用ASP.NET Core提供的服務(wù)

Startup類的ConfigureServices方法負(fù)責(zé)定義應(yīng)用程序?qū)⑹褂玫姆?wù),包括平臺(tái)自帶的功能,比如,Entity Framework Core 和 ASP.NET Core MVC。除了IServiceCollection提供的幾個(gè)服務(wù)之外,可以使用一些擴(kuò)展方法(AddDbContext,AddMvc,AddTransient等)向容器添加和注冊(cè)額外服務(wù):

public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddDbContext<AccessManagementContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                providerOptions => providerOptions.EnableRetryOnFailure()));
            services.AddTransient<ICompanyServices, CompanyServices>();

        }

ASP.NET Core 提供的功能和中間件,遵循約定使用一個(gè)單一的AddService擴(kuò)展方法來(lái)注冊(cè)所有該功能所需的服務(wù)。

3.注冊(cè)自己的服務(wù)

我們可以按照 services.AddTransient<ICompanyServices, CompanyServices>(); 這種寫(xiě)法注冊(cè)自己的服務(wù)。第一個(gè)范型類型表示將要從容器中請(qǐng)求的類型(通常是一個(gè)接口)。第二個(gè)范型類型表示將由容器實(shí)例化并且用于完成請(qǐng)求的具體類型。

AddTransient 方法用于將抽象類型映射到為每一個(gè)需要它的對(duì)象分別實(shí)例化的具體服務(wù)。為注冊(cè)的每一個(gè)服務(wù)選擇合適的生命周期很重要,后面會(huì)介紹到。

下面是示例是注冊(cè)自己的服務(wù):

1.接口

public interface IAccountServices
    {
        Task<List<AccountViewModel>> GetList();
    }

2.實(shí)現(xiàn)類

public class AccountServices:IAccountServices
    {
        AccessManagementContext _context;
        public AccountServices(AccessManagementContext context)
        {
            _context = context;//在構(gòu)造函數(shù)中注入
        }

        public async Task<List<Account>> GetList()
        {
            try
            {
                var query = _context.Account.ToListAsync();
                 return query ;
            }
            catch (Exception ex)
            {
                return null;
            }

        }
}

3.在ConfigureServices中注冊(cè)自定義的服務(wù)和EF上下文AccessManagementContext 

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddDbContext<AccessManagementContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                providerOptions => providerOptions.EnableRetryOnFailure()));
            services.AddTransient<IAccountServices,AccountServices>();

        }

4.在Controller構(gòu)造函數(shù)中依賴注入

public class AccountController : Controller
    {
        private IAccountServices _accountServices;
        public AccountController(IAccountServices accountServices)
        {
            _accountServices = accountServices;
        }
        // GET: Account
        public async Task<ActionResult> Index()
        {
            var vms = await _accountServices.GetList();
            return View(vms);
        }

4.服務(wù)的生命周期和注冊(cè)選項(xiàng)

ASP.NET 服務(wù)生命周期:

  • 1.Transient 瞬時(shí)
    Transient 生命周期服務(wù)在他們每次請(qǐng)求時(shí)被創(chuàng)建。適合輕量級(jí),無(wú)狀態(tài)的服務(wù)。

  • 2.Scoped 作用域
    Scoped生命周期在每次請(qǐng)求時(shí)創(chuàng)建一次。

  • 3.Singleton 單例
    Singleton 生命周期服務(wù)在它們第一次請(qǐng)求時(shí)創(chuàng)建,并且每個(gè)后續(xù)請(qǐng)求使用相同的實(shí)例。

服務(wù)可以用多種方式在容器中注冊(cè),除了之前的注冊(cè)方法,還可以指定一個(gè)工廠,它將被用來(lái)創(chuàng)建需要的實(shí)例。后面會(huì)詳細(xì)介紹其他的注冊(cè)方法。

下面用一個(gè)簡(jiǎn)單的示例介紹每個(gè)生命周期:

1.創(chuàng)建接口:

namespace MVCTest.Interfaces
{
    public interface IOperation
    {
        /// <summary>
        /// 唯一標(biāo)識(shí)
        /// </summary>
        Guid OperationId { get;  }
    }

    public interface IOperationTransient: IOperation
    {
    }

    public interface IOperationScoped : IOperation
    {
    }

    public interface IOperationSingleton : IOperation
    {
    }

    public interface IOperationInstance : IOperation
    {
    }
}

2.實(shí)現(xiàn)類

/// <summary>
    /// 實(shí)現(xiàn)所有接口
    /// </summary>
    public class Operation: IOperation, IOperationTransient,
        IOperationScoped, IOperationSingleton, IOperationInstance
    {
        public Operation()
        {
            OperationId = Guid.NewGuid();
        }
        public Operation(Guid operationId)
        {
            if (operationId == null)
            {
                OperationId = Guid.NewGuid();
            }
            OperationId = operationId;
        }

        public Guid OperationId { get; }
    }

3.注冊(cè)到容器

public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IOperationTransient, Operation>();
            services.AddScoped<IOperationScoped, Operation>();
            services.AddSingleton<IOperationSingleton, Operation>();
            services.AddSingleton<IOperationInstance, Operation>();
            services.AddTransient<OperationServices, OperationServices>();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

4.上面還注冊(cè)了 OperationServices ,用來(lái)測(cè)試單例模式(單例生命周期服務(wù)中所有請(qǐng)求使用第一次實(shí)例化的服務(wù))和 作用域生命周期服務(wù)在每次請(qǐng)求時(shí)只創(chuàng)建一次,不管幾個(gè)地方用到實(shí)例

public class OperationServices
    {
        public IOperationTransient OperationTransient { get;  }
        public IOperationScoped OperationScoped { get;  }
        public IOperationSingleton OperationSingleton { get;  }
        public IOperationInstance OperationInstance { get;  }

        public OperationServices(IOperationTransient operationTransient,
            IOperationScoped operationScoped,
            IOperationSingleton operationSingleton,
            IOperationInstance operationInstance)
        {
            OperationTransient = operationTransient;
            OperationScoped = operationScoped;
            OperationSingleton = operationSingleton;
            OperationInstance = operationInstance;
        }
    }

5.在Controller中使用

public class OperationController : Controller
    {
        public IOperationTransient OperationTransient { get; }
        public IOperationScoped OperationScoped { get; }
        public IOperationSingleton OperationSingleton { get; }
        public IOperationInstance OperationInstance { get; }
        public OperationServices _operationServices;

        public OperationController(IOperationTransient operationTransient,
            IOperationScoped operationScoped,
            IOperationSingleton operationSingleton,
            IOperationInstance operationInstance,
            OperationServices operationServices)
        {
            OperationTransient = operationTransient;
            OperationScoped = operationScoped;
            OperationSingleton = operationSingleton;
            OperationInstance = operationInstance;
            _operationServices = operationServices;
        }
        // GET: Operation
        public ActionResult Index()
        {
            ViewBag.OperationTransient = OperationTransient;
            ViewBag.OperationScoped = OperationScoped;
            ViewBag.OperationSingleton = OperationSingleton;
            ViewBag.OperationInstance = OperationInstance;
            ViewBag._operationServices = _operationServices;
            return View();
        }
}

6.Index顯示

@{
    ViewData["Title"] = "Index";
}

<div>
    <h2>Controller Operations</h2>
    <h3>OperationTransient: @ViewBag.OperationTransient.OperationId</h3>
    <h3>OperationScoped: @ViewBag.OperationScoped.OperationId</h3>
    <h3>OperationSingleton: @ViewBag.OperationSingleton.OperationId</h3>
    <h3>OperationInstance: @ViewBag.OperationInstance.OperationId</h3>
</div>
<div>
    <h2>Services Operations</h2>
    <h3>OperationTransient: @ViewBag._operationServices.OperationTransient.OperationId</h3>
    <h3>OperationScoped: @ViewBag._operationServices.OperationScoped.OperationId</h3>
    <h3>OperationSingleton: @ViewBag._operationServices.OperationSingleton.OperationId</h3>
    <h3>OperationInstance: @ViewBag._operationServices.OperationInstance.OperationId</h3>
</div>

7.運(yùn)行結(jié)果

ASP.NET?Core依賴注入實(shí)例分析

可以看到,單例生命周期服務(wù)每一次請(qǐng)求的標(biāo)識(shí)一樣。作用域生命周期的服務(wù),在一次請(qǐng)求中使用的同一個(gè)實(shí)例,第二次請(qǐng)求創(chuàng)建新的實(shí)例。

5.請(qǐng)求服務(wù)

來(lái)自HttpContext的一次ASP.NET 請(qǐng)求中,可用的服務(wù)是通過(guò)RequestServices集合公開(kāi)的。

請(qǐng)求服務(wù)將你配置的服務(wù)和請(qǐng)求描述為應(yīng)用程序的一部分。在子的對(duì)象指定依賴之后,這些滿足要求的對(duì)象可通過(guò)查找RequestServices中對(duì)應(yīng)的類型得到,而不是ApplicationServices。

6.設(shè)計(jì)依賴注入服務(wù)

在自定義的服務(wù)中,避免使用靜態(tài)方法和直接實(shí)例化依賴的類型,而是通過(guò)依賴注入請(qǐng)求它。(New is Glue)

如果類有太多的依賴關(guān)系被注入時(shí),通常表明你的類試圖做的太多(違反了單一職責(zé)原則),需要轉(zhuǎn)移一些職責(zé)。

同樣,Controller類應(yīng)該重點(diǎn)關(guān)注UI,因此業(yè)務(wù)邏輯和數(shù)據(jù)訪問(wèn)等細(xì)節(jié)應(yīng)該在其他類中。

以上就是“ASP.NET Core依賴注入實(shí)例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI