日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

service 层注入不同的数据源_.NET 理论基础+实战控制台程序实现AutoFac注入

發(fā)布時(shí)間:2025/3/15 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 service 层注入不同的数据源_.NET 理论基础+实战控制台程序实现AutoFac注入 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

(給DotNet加星標(biāo),提升.Net技能)

轉(zhuǎn)自:在7樓?

cnblogs.com/RayWang/p/11128554.html

簡(jiǎn)介

該系列共5篇文章,旨在以實(shí)戰(zhàn)模式,在.NET下的

  • 控制臺(tái)程序

  • Framework Mvc程序

  • Framework WebApi程序

  • Core Api程序

分別實(shí)現(xiàn)依賴注入。

其中.NET? Framework框架主要以如何引入AutoFac作為容器以及如何運(yùn)用AuotoFac為主,.NET Core框架除了研究引入AutoFac的兩種方式,同時(shí)也運(yùn)用反射技巧對(duì)其自帶的DI框架進(jìn)行了初步封裝,實(shí)現(xiàn)了相同的依賴注入效果。

項(xiàng)目架構(gòu)如下圖:

GitHub源碼地址:https://github.com/WangRui321/Ray.EssayNotes.AutoFac

適用對(duì)象

該項(xiàng)目主要實(shí)戰(zhàn)為主,理論部分我會(huì)結(jié)合例子和代碼,深入淺出地闡述,如果你是:

  • 從來沒聽過IoC、DI這些勞什子

  • 了解一些依賴注入的理論知識(shí)但是缺乏實(shí)戰(zhàn)

  • 在.Net Framework下已熟練運(yùn)用依賴注入,但在.NET Core還比較陌生

只要你花上半個(gè)小時(shí)認(rèn)真讀完每一句話,我有信心這篇文章一定會(huì)對(duì)你有所幫助。

如果你是:

  • 發(fā)量比我還少的秒天秒地的大牛

那么也歡迎閱讀,雖然可能對(duì)你幫助并不大,但是歡迎提供寶貴的意見,有寫的不好的地方可以互相交流~

理論基礎(chǔ)

依賴

依賴,簡(jiǎn)單說就是,當(dāng)一個(gè)類需要另一個(gè)類協(xié)作來完成工作的時(shí)候就產(chǎn)生了依賴。這也是耦合的一種形式。

舉個(gè)例子,比如標(biāo)準(zhǔn)的三層架構(gòu)模式

數(shù)據(jù)訪問層(DAL)代碼:

///
/// 學(xué)生倉儲(chǔ)
///
public class StudentRepository
{
public string GetName(long id){
return "學(xué)生張三";//造個(gè)假數(shù)據(jù)返回
}
}

業(yè)務(wù)層(BLL)代碼:

///
/// 學(xué)生邏輯處理
///
public class StudentService
{
private readonly StudentRepository _studentRepository;
public StudentService(){
_studentRepository = new StudentRepository();
}
public string GetStuName(long id){
var stu = _studentRepository.Get(id);
return stu.Name;
}
}

其中,StudentService的實(shí)現(xiàn),就必須要依賴于StudentRepository。而且這是一種緊耦合,一旦StudentRepository有任何更改,必然導(dǎo)致StudentService的代碼同樣也需要更改,這種情況是程序員們不愿意看到的。

接口驅(qū)動(dòng)

接口驅(qū)動(dòng)是為了實(shí)現(xiàn)一個(gè)設(shè)計(jì)原則:要依賴于抽象,而不是具體的實(shí)現(xiàn)。

還拿上面的例子說明,現(xiàn)在我添加一個(gè)DAL的接口層,IStudentRepository,抽象出所需方法:

///
/// 學(xué)生倉儲(chǔ)interface
///
public interface IStudentRepository
{
string GetName(long id);
}

然后讓StudentRepository去實(shí)現(xiàn)這個(gè)接口:

///
/// 學(xué)生倉儲(chǔ)
///
public class StudentRepository : IStudentRepository
{
public string GetName(long id){
return "學(xué)生張三";//造個(gè)假數(shù)據(jù)返回
}
}

然后在StudentService里只依賴于IStudentRepository,以后的增刪改查都通過IStudentRepository這個(gè)抽象來做:

///
/// 學(xué)生邏輯處理
///
public class StudentService
{
private readonly IStudentRepository _studentRepository;
public StudentService(){
_studentRepository = new StudentRepository();
}
public string GetStuName(long id){
var stu = _studentRepository.Get(id);
return stu.Name;
}
}

這樣做的好處有兩個(gè),一個(gè)是低耦合,一個(gè)是職責(zé)清晰。如果對(duì)此還有懷疑的話,我們可以想象一個(gè)情景,就是負(fù)責(zé)寫StudentService的是程序員A,負(fù)責(zé)寫StudentRepository的是另一個(gè)程序員B,那么:

  • 針對(duì)程序員A

我(程序員A)只需要關(guān)注業(yè)務(wù)邏輯層面,如果我需要從倉儲(chǔ)層拿數(shù)據(jù)庫的數(shù)據(jù),比如我需要根據(jù)Id獲取學(xué)生實(shí)體,那么我只需要去IStudentRepository找Get(long id)函數(shù)就可以了,至于實(shí)現(xiàn)它的倉儲(chǔ)怎么實(shí)現(xiàn)這個(gè)方法我完全不用管,你怎么從數(shù)據(jù)庫拿數(shù)據(jù)不是我該關(guān)心的事情。

  • 針對(duì)程序員B

我(程序員B)的工作就是實(shí)現(xiàn)IStudentRepository接口的所有方法就行了,簡(jiǎn)單而明確,至于誰來調(diào)用我,我不用管。IStudentRepository里有根據(jù)Id獲取學(xué)生姓名的方法,我實(shí)現(xiàn)了就行,至于業(yè)務(wù)邏輯層拿這個(gè)名字干啥,那不是我要關(guān)心的事情。

這樣看的話是不是彼此的職責(zé)就清晰多了,更進(jìn)一步再舉個(gè)極端的例子:

比如程序員B是個(gè)實(shí)習(xí)生,整天劃水摸魚,技術(shù)停留在上個(gè)世紀(jì),結(jié)果他寫的倉儲(chǔ)層讀取數(shù)據(jù)庫全部用的手寫sql語句的方式,極難維護(hù),后來被領(lǐng)導(dǎo)發(fā)現(xiàn)領(lǐng)了盒飯,公司安排了另一個(gè)程序員C來重寫倉儲(chǔ)層,C這時(shí)不需要?jiǎng)悠渌a,只需要新建一個(gè)倉儲(chǔ)StudentNewRepository,然后實(shí)現(xiàn)之前的IStudentRepository,C使用Dapper或者EF,寫完新的倉儲(chǔ)層之后,剩下的只需要在StudentService里改一個(gè)地方就行了:

public StudentService(){
_studentRepository = new StudentNewRepository();
}

是不是很清晰,耦合不會(huì)像以前那么重。

其實(shí)對(duì)于這個(gè)小例子來說,接口驅(qū)動(dòng)的優(yōu)勢(shì)還不太明顯,但是在系統(tǒng)層面優(yōu)勢(shì)就會(huì)被放大。比如上面換倉儲(chǔ)的例子,雖然職責(zé)是清晰了,但是項(xiàng)目里有幾個(gè)Service就需要改幾個(gè)地方,還是很麻煩。

原因就是上面講的,這是一種依賴關(guān)系,Service要依賴Repository,有沒有一種方法可以讓這種控制關(guān)系反轉(zhuǎn)過來呢?當(dāng)Service需要使用Repository,有沒有辦法讓我需要的Repository自己注入到我這里來?

當(dāng)然有,這就是我們將要實(shí)現(xiàn)的依賴注入。使用依賴注入后你會(huì)發(fā)現(xiàn),當(dāng)C寫完新的倉儲(chǔ)后,業(yè)務(wù)邏輯層(StudentService)是不需要改任何代碼的,所有的Service都不需要一個(gè)一個(gè)去改,直接在注入的時(shí)候修改規(guī)則,不要注入以前老的直接注入新的倉儲(chǔ)就可以了。

面向接口后的架構(gòu):

什么是IoC

IoC,全稱Inversion of Control,即“控制反轉(zhuǎn)”,是一種設(shè)計(jì)原則,最早由Martin Fowler提出,因?yàn)槠淅碚撎岢鰰r(shí)間和成熟時(shí)間相對(duì)較晚,所以并沒有被包含在GoF的《設(shè)計(jì)模式》中。

什么是DI

DI,全稱Dependency Injection,即依賴注入,是實(shí)現(xiàn)IoC的其中一種設(shè)計(jì)方法。

其特征是通過一些技巧,將依賴的對(duì)象注入到調(diào)用者當(dāng)中。(比如把Repository注入到Service當(dāng)中)

這里說的技巧目前主要指的就是引入容器,先把所有會(huì)產(chǎn)生依賴的對(duì)象統(tǒng)一添加到容器當(dāng)中,比如StudentRepository和StudentService,把分配權(quán)限交給容器,當(dāng)StudentService內(nèi)部需要使用StudentRepository時(shí),這時(shí)不應(yīng)該讓它自己new出來一個(gè),而是通過容器,把StudentRepository注入到StudentService當(dāng)中。

這就是名稱“依賴注入”的由來。

DI和IoC有什么區(qū)別

這是個(gè)老生常談的問題了,而且這兩個(gè)名字經(jīng)常在各種大牛和偽大牛的吹逼現(xiàn)場(chǎng)頻繁出現(xiàn) ,聽的新手云里霧里,莫名感到神圣不可侵犯。那么DI和IoC是同一個(gè)東西嗎?如果不是,它們又有什么區(qū)別呢?

回答很簡(jiǎn)單:不是一個(gè)東西。

區(qū)別也很簡(jiǎn)單,一句話概括就是:IoC是一種很寬泛的理念,DI是實(shí)現(xiàn)了IoC的其中一種方法。

說到這里我已經(jīng)感覺到屏幕后的你性感地添了一下嘴唇,囤積好口水,準(zhǔn)備開始噴我了。

先別慌,我有證據(jù),我們先來看下微軟怎么說:

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies.

地址:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2

翻譯過來就是“ASP.NET Core支持依賴注入(DI)的軟件設(shè)計(jì)模式,該模式是一種在類和它依賴的對(duì)象之間實(shí)現(xiàn)了控制反轉(zhuǎn)(IoC)的技術(shù)”。

如果有人覺得辣雞微軟不夠權(quán)威,那我們?nèi)タ聪翴oC以及DI這兩個(gè)概念的發(fā)明人——Martin Fowler怎么說:

幾位輕量級(jí)容器的作者曾驕傲地對(duì)我說:這些容器非常有用,因?yàn)樗鼈儗?shí)現(xiàn)了控制反轉(zhuǎn)。這樣的說辭讓我深感迷惑:控制反轉(zhuǎn)是框架所共有的特征,如果僅僅因?yàn)槭褂昧丝刂品崔D(zhuǎn)就認(rèn)為這些輕量級(jí)容器與眾不同,就好象在說我的轎車是與眾不同的,因?yàn)樗兴膫€(gè)輪子。

因此,我想我們需要給這個(gè)模式起一個(gè)更能說明其特點(diǎn)的名字——”控制反轉(zhuǎn)”這個(gè)名字太泛了,常常讓人有些迷惑。經(jīng)與多位IoC 愛好者討論之后,我們決定將這個(gè)模式叫做”依賴注入”(Dependency Injection)。

地址:http://insights.thoughtworkers.org/injection/

Martin Fowler說的比較委婉,其實(shí)說白了就是建議我們,不要亂用IoC裝逼,IoC是一種設(shè)計(jì)理念,很寬泛,你把程序里的一個(gè)寫死的變量改成從配置文件里讀取也是一種控制反轉(zhuǎn)(由程序控制反轉(zhuǎn)為由框架控制),你把這個(gè)配置改成用戶UI界面的一個(gè)輸入文本框由用戶輸入也是一種控制反轉(zhuǎn)(由框架控制反轉(zhuǎn)為由用戶自己控制)。

所以,如果確定討論的模式是DI,那么就表述為DI,還是盡量少用IoC這種寬泛的表達(dá)。

AutoFac

AutoFac是一個(gè)開源的輕量級(jí)的DI容器,也是.net下最受大家歡迎的實(shí)現(xiàn)依賴注入的工具之一,通過AutoFac我們可以很方便的實(shí)現(xiàn)一些DI的騷操作。

實(shí)戰(zhàn)控制臺(tái)程序依賴注入

目標(biāo)很簡(jiǎn)單,就是控制臺(tái)程序啟動(dòng)后,將學(xué)生姓名打印出來。

程序啟動(dòng)流程是,控制臺(tái)主程序調(diào)用Service層,Service層調(diào)用Repository層獲取數(shù)據(jù)(示例項(xiàng)目的倉儲(chǔ)層沒有連接數(shù)據(jù)庫,只是直接造個(gè)假數(shù)據(jù)返回)。

沒有依賴注入的情況下,肯定是主程序會(huì)new一個(gè)StudentService,StudentService里會(huì)new一個(gè)StudentRepository,現(xiàn)在引入依賴注入后,就不應(yīng)該這么new出來了,而是通過容器注入,也就是容器會(huì)把StudentRepository自動(dòng)注入到StudentService當(dāng)中。

架構(gòu)

實(shí)體層

學(xué)生實(shí)體類StudentEntity:

namespace Ray.EssayNotes.AutoFac.Model
{
/// 學(xué)生實(shí)體
public class StudentEntity
{
/// 唯一標(biāo)識(shí)
public long Id { get; set; }
/// 姓名
public string Name { get; set; }
/// 成績(jī)
public int Grade { get; set; }
}
}

倉儲(chǔ)層

IStudentRepository接口:

using Ray.EssayNotes.AutoFac.Model;
namespace Ray.EssayNotes.AutoFac.Repository.IRepository
{
/// 學(xué)生倉儲(chǔ)interface
public interface IStudentRepository
{
string GetName(long id);
}
}

StudentRepository倉儲(chǔ)類:

using Ray.EssayNotes.AutoFac.Model;
using Ray.EssayNotes.AutoFac.Repository.IRepository;

namespace Ray.EssayNotes.AutoFac.Repository.Repository
{
///
/// 學(xué)生倉儲(chǔ)
///
public class StudentRepository : IStudentRepository
{
public string GetName(long id){
return "學(xué)生張三";//造個(gè)假數(shù)據(jù)返回
}
}
}

Service層

IStudentService接口

namespace Ray.EssayNotes.AutoFac.Service.IService
{
///
/// 學(xué)生邏輯處理interface
///
public interface IStudentService
{
string GetStuName(long id);
}
}

StudentService類:

using Ray.EssayNotes.AutoFac.Repository.IRepository;
using Ray.EssayNotes.AutoFac.Repository.Repository;
using Ray.EssayNotes.AutoFac.Service.IService;
namespace Ray.EssayNotes.AutoFac.Service.Service
{
///
/// 學(xué)生邏輯處理
///
public class StudentService : IStudentService
{
private readonly IStudentRepository _studentRepository;
///
/// 構(gòu)造注入
///
///
public StudentService(IStudentRepository studentRepository){
_studentRepository = studentRepository;
}
public string GetStuName(long id){
var stu = _studentRepository.Get(id);
return stu.Name;
}
}
}

其中構(gòu)造函數(shù)是一個(gè)有參的函數(shù),參數(shù)是學(xué)生倉儲(chǔ),這個(gè)后面依賴注入時(shí)會(huì)用。

AutoFac容器

需要先通過Nuget導(dǎo)入Autofac包:

using System;
using System.Reflection;
//
using Autofac;
using Autofac.Core;
//
using Ray.EssayNotes.AutoFac.Repository.IRepository;
using Ray.EssayNotes.AutoFac.Repository.Repository;
using Ray.EssayNotes.AutoFac.Service.IService;
using Ray.EssayNotes.AutoFac.Service.Service;

namespace Ray.EssayNotes.AutoFac.Infrastructure.Ioc
{
///
/// 控制臺(tái)程序容器
///
public static class Container
{
///
/// 容器
///
public static IContainer Instance;

///
/// 初始化容器
///
///
public static void Init(){

//新建容器構(gòu)建器,用于注冊(cè)組件和服務(wù)
var builder = new ContainerBuilder();
//自定義注冊(cè)
MyBuild(builder);
//利用構(gòu)建器創(chuàng)建容器
Instance = builder.Build();
}

///
/// 自定義注冊(cè)
///
///
public static void MyBuild(ContainerBuilder builder){
builder.RegisterType().As();
builder.RegisterType().As();
}
}
}

其中:

  • public static IContainer Instance

    為單例容器

  • Init()方法

    用于初始化容器,即往容器中添加對(duì)象,我們把這個(gè)添加的過程稱為注冊(cè)(Register)。

    ContainerBuilder為AutoFac定義的容器構(gòu)造器,我們通過使用它往容器內(nèi)注冊(cè)對(duì)象。

  • MyBuild(ContainerBuilder builder)方法

    我們具體注冊(cè)的實(shí)現(xiàn)函數(shù)。RegisterType是AutoFac封裝的一種最基本的注冊(cè)方法,傳入的泛型(StudentService)就是我們欲添加到容器的對(duì)象;As函數(shù)負(fù)責(zé)綁定注冊(cè)對(duì)象的暴露類型,一般是以其實(shí)現(xiàn)的接口類型暴露,這個(gè)暴露類型是我們后面去容器內(nèi)查找對(duì)象時(shí)使用的搜索標(biāo)識(shí),我們從容器外部只有通過暴露類型才能找到容器內(nèi)的對(duì)象。

主程序

需要先Nuget導(dǎo)入AutoFac程序包:

using System;
//
using Autofac;
//
using Ray.EssayNotes.AutoFac.Infrastructure.Ioc;
using Ray.EssayNotes.AutoFac.Service.IService;

namespace Ray.EssayNotes.AutoFac.ConsoleApp
{
class Program
{
static void Main(string[] args){
Container.Init();//初始化容器,將需要用到的組件添加到容器中
PrintStudentName(10001);
Console.ReadKey();
}
///
/// 輸出學(xué)生姓名
///
///
public static void PrintStudentName(long id){

//從容器中解析出對(duì)象
IStudentService stuService = Container.Instance.Resolve();string name = stuService.GetStuName(id);
Console.WriteLine(name);
}
}
}

進(jìn)入Main函數(shù),先調(diào)用容器的初始化函數(shù),該函數(shù)執(zhí)行成功后,StudentRepository和StudentService就被注冊(cè)到容器中了。

然后調(diào)用打印學(xué)生姓名的函數(shù),其中Resolve()方法是AutoFac封裝的容器的解析方法,傳入的泛型就是之前注冊(cè)時(shí)的暴露類型,下面可以詳細(xì)看下這一步到底發(fā)生了哪些事情:

  • 容器根據(jù)暴露類型解析對(duì)象

也就是容器會(huì)根據(jù)暴露類型IStudentService去容器內(nèi)部找到其對(duì)應(yīng)類(即StudentService),找到后會(huì)試圖實(shí)例化一個(gè)對(duì)象出來。

  • 實(shí)例化StudentService

AutoFac容器在解析StudentService的時(shí)候,會(huì)調(diào)用StudentService的構(gòu)造函數(shù)進(jìn)行實(shí)例化。

  • 構(gòu)造注入

AutoFac容器發(fā)現(xiàn)StudentService的構(gòu)造函數(shù)需要一個(gè)IStudnetRepository類型的參數(shù),于是會(huì)自動(dòng)去容器內(nèi)尋找,根據(jù)這個(gè)暴露類型找到對(duì)應(yīng)的StudnetRepository后,自動(dòng)將其注入到了StudentService當(dāng)中

經(jīng)過這幾步,一個(gè)簡(jiǎn)單的基于依賴注入的程序就完成了。

結(jié)果

我們將控制臺(tái)程序設(shè)置為啟動(dòng)項(xiàng)目,點(diǎn)擊運(yùn)行,如圖調(diào)用成功:

如果把調(diào)試斷點(diǎn)加在容器初始化函數(shù)里,可以很清晰的看到哪些對(duì)象被注冊(cè)到了容器里:

補(bǔ)充

使用控制臺(tái)程序本來是為了突出容器的概念,但是容易造成一些誤解,DI的最終形態(tài)可以參考源碼里的Api項(xiàng)目和MVC項(xiàng)目,本來想循序漸進(jìn),先第一章控制臺(tái)引入容器的概念,然后第二章講批量注冊(cè)、注入泛型、生命周期域管理,第三章講Api和MVC項(xiàng)目,最后兩章講下.net core的DI,但是這里還是先說下吧:

誤解1:每次添加Service和Repository都要去注冊(cè),不是更麻煩?

其實(shí)是不需要一個(gè)一個(gè)注冊(cè)的,運(yùn)用批量注冊(cè)后容器內(nèi)部的代碼是這樣的,可以直接批量注冊(cè)所有的:

///
/// .net framework MVC程序容器
///
public static class MvcContainer
{
public static IContainer Instance;

///
/// 初始化容器
///
///
///
public static void Init(Func func = null){
//新建容器構(gòu)建器,用于注冊(cè)組件和服務(wù)
var builder = new ContainerBuilder();
//注冊(cè)組件
MyBuild(builder);
func?.Invoke(builder);
//利用構(gòu)建器創(chuàng)建容器
Instance = builder.Build();
//將AutoFac設(shè)置為系統(tǒng)DI解析器
System.Web.Mvc.DependencyResolver.SetResolver(new AutofacDependencyResolver(Instance));
}
public static void MyBuild(ContainerBuilder builder){
Assembly[] assemblies = Helpers.ReflectionHelper.GetAllAssembliesWeb();
//批量注冊(cè)所有倉儲(chǔ) && Service
builder.RegisterAssemblyTypes(assemblies)//程序集內(nèi)所有具象類(concrete classes)
.Where(cc => cc.Name.EndsWith("Repository") |//篩選
cc.Name.EndsWith("Service"))
.PublicOnly()//只要public訪問權(quán)限的
.Where(cc => cc.IsClass)//只要class型(主要為了排除值和interface類型)
.AsImplementedInterfaces();//自動(dòng)以其實(shí)現(xiàn)的所有接口類型暴露(包括IDisposable接口)
//注冊(cè)泛型倉儲(chǔ)
builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>));

//注冊(cè)Controller
Assembly mvcAssembly = assemblies.FirstOrDefault(x => x.FullName.Contains(".NetFrameworkMvc"));
builder.RegisterControllers(mvcAssembly);
}
}

誤解2:每次使用都要解析下,還不如直接new

好吧,其實(shí)也是不需要自己去解析的,最終形態(tài)的Controller入口是這樣的,直接在構(gòu)造函數(shù)里寫就行了:

public class StudentController : Controller
{
private readonly IStudentService _studentService;
public StudentController(IStudentService studentService){
_studentService = studentService;
}
///
/// 獲取學(xué)生姓名
///
///
///
public string GetStuNameById(long id){
return _studentService.GetStuName(id);
}
}

就是直接在構(gòu)造函數(shù)里注入就可以了。

誤解3:依賴注入是不是過度設(shè)計(jì)?

首先DI是一個(gè)設(shè)計(jì)模式(design pattern),其本身完全不存在過不過度的問題,這完全取決于用的人和怎么用。

另外,在.NET Core中,DI被提到了一個(gè)很重要的地位,如果想要了解.NET Core,理解DI是必不可少的。

推薦閱讀

(點(diǎn)擊標(biāo)題可跳轉(zhuǎn)閱讀)

ASP.NET Core系列之Dependency injection(依賴注入)

.NET中擴(kuò)展方法和Enumerable

.NET 架構(gòu)開發(fā) 應(yīng)知應(yīng)會(huì)

看完本文有收獲?請(qǐng)轉(zhuǎn)發(fā)分享給更多人

關(guān)注「DotNet」加星標(biāo),提升.Net技能?

好文章,我在看??

總結(jié)

以上是生活随笔為你收集整理的service 层注入不同的数据源_.NET 理论基础+实战控制台程序实现AutoFac注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。