最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

.Net Core中使用Autofac替換自帶的DI容器的示例

 更新時間:2021年06月23日 10:34:22   作者:暢飲無緒  
Autofac比Core中自帶的DI功能強大的多,比如:屬性注入、基于名稱注入、子容器、自定生存期管理、遲緩初始化,本文就詳細的來介紹一下.Net Core Autofac替換DI容器,感興趣的可以了解一下

為什么叫淺談呢?就是字面上的意思,講得比較淺,又不是不能用(這樣是不對的)?。?!

Aufofac大家都不陌生了,說是.Net生態(tài)下最優(yōu)秀的IOC框架那是一點都過分。用的人多了,使用教程也十分豐富,官網教程也比較詳細(如果英文功底還不錯的話)。

那我為什么還要寫這樣一篇博客呢,一是用作學習筆記,二就是閑的。

廢話不多說,開始正文

項目創(chuàng)建

云創(chuàng)建一個.Net Core Api項目,然后再添加一個類庫,大概就是下面這樣的結構:

新建一個類庫項目,分別添加一個接口文件與類文件:

就這樣,我們的演示方案就搭建完成了,下面就到了演示階段。

方案演示

原始方案

俗話說的好,沒有對象 new 一個就對了:

[HttpGet]
public string Original()
{
    IUserService userService = new UserService();
    return userService.GetName("Original");
}

結果當然是沒問題的:

.Net Core自帶DI

微軟給我們提供的 DI 解決方案。如果是小項目,需要注入的服務不多,簡直無敵好用,缺點就是不能批量注入,下面我們來復習一下:

先在 Startup 里面的 ConfigureServices 方法內注入(默認且只能構造函數注入)

services.AddScoped<IUserService, UserService>();

然后在控制器中拿到剛才注入的服務:

 public class DefaultController : ControllerBase
  {
      private readonly IUserService userService;
      public DefaultController(IUserService _userService)
      {
          this.userService = _userService;
      } 
     [HttpGet]
     public string CoreDI()
     {
         return userService.GetName("CoreDI");
     }
 }

很顯然,一點問題都沒有:

Autofac

注意事項說在前面:

在 .Net Core2 中一般是把StartupConfigureServices方法返回值類型改為IServiceProvider,然后通過構建Autofac容器并注入服務后返回。

在 .Net Core3.0之后,集成方式做了部分調整

下面演示的版本是.Net Core 3.1,也就是調整后的版本。

1、先引用 Autofac 的包,看看這下載次數

2、在 Program 中改用 Autofac 來實現依賴注入

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        // 就是這句
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

3、添加我們自定義的 Autofac 注冊類,并注冊我們需要的服務(默認構造函數注入,支持屬性注入)

public class AutofacModuleRegister : Autofac.Module
{
    //重寫Autofac管道Load方法,在這里注冊注入
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<UserService>().As<IUserService>();
   }
}

4、在 Startup 類中添加方法:ConfigureContainer,

public void ConfigureContainer(ContainerBuilder builder)
{
    // 直接用Autofac注冊我們自定義的 
    builder.RegisterModule(new AutofacModuleRegister());
}

5、大功告成,控制器內的方法甚至不用去改

public class DefaultController : ControllerBase
 {
     private readonly IUserService userService;
     public DefaultController(IUserService _userService)
     {
         this.userService = _userService;
     }

     [HttpGet]
     public string Autofac()
     {
         return userService.GetName("Autofac");
     }
 }

演示到這里就結束了,是不是感覺 Autofac 比自帶的 DI 還要麻煩。其實不然,下面我們就來看看 Autofac 對比自帶 DI 的一些特有特性。

不同的特性

批量注入

之前的項目我們有了用戶 UserService,需求更新,加入了商品(ProductService),有了商品那又怎么能少得了訂單(OrderService),那后面是不是還得有售后、物流、倉庫、營銷......

如果是.Net Core 自帶的注入框架,那就只能不停的:

services.AddScoped<IProductService, ProductService>();
services.AddScoped<IOrderService, OrderService>();
......

這時候,Autofac 的好處就體現出來了:批量注入。

我們先回到上面的:AutofacModuleRegister 類,加入下面這段代碼:

// 服務項目程序集
Assembly service = Assembly.Load("XXX.Service");
// 服務接口項目程序集
Assembly iservice = Assembly.Load("XXX.IService");
builder.RegisterAssemblyTypes(service, iservice)
    .Where(t => t.FullName.EndsWith("Service") && !t.IsAbstract)
    .InstancePerLifetimeScope()
    .AsImplementedInterfaces();

上面的代碼就是批量注入 XXX.Service 與 XXX.IService 項目下的服務與接口。

注意:如果需要注入的服務沒有 interfac ,那么builder.RegisterAssemblyTypes 就只需要傳一個程序集就OK了。如果服務與接口同在一個項目,那也是要傳兩個程序集的哦。

然后我們在控制器去通過構造函數獲取注入的實例:

private readonly IUserService userService;
private readonly IProductService productService;

public DefaultController(IUserService _userService, IProductService _productService)
{
    this.userService = _userService;
    this.productService = _productService;
}

再對之前的 Autofac 接口添油加醋:

[HttpGet]
public string Autofac()
{
    var name = userService.GetName("Autofac");
    return productService.Buy(name, "批量注入");
}

結果自然是沒有問題的,如果后續(xù)需要加入其它服務都不用再單獨注入了,是不是優(yōu)點就體現出來了。批量注入還有一些其它的玩法,比如篩選類名,篩選父類等。

屬性注入

.Net Core 自帶的 DI 框架與 Autofac 默認都是構造函數注入,官方建議也是構造函數注入。

但是有些同學可能就不喜歡構造函數注入,再加上有些場景確實不適合構造函數注入(比如基類實體),所以 Autofac 也支持屬性注入,下面我們來看看使用方法,在之前批量注入的基礎上,我們簡單改造一下:

Assembly service = Assembly.Load("Autofac.Service");
Assembly iservice = Assembly.Load("Autofac.Service");
builder.RegisterAssemblyTypes(service, iservice)
    .Where(t => t.FullName.EndsWith("Service") && !t.IsAbstract)
    .InstancePerLifetimeScope()
    .AsImplementedInterfaces()
    .PropertiesAutowired(); // 屬性注入

對比構造函數注入,屬性注入就多追加了PropertiesAutowired() 函數,控制器內修改:

public IUserService userService { get; set; }
public IProductService productService { get; set; }

注意:屬性注入記得將屬性的訪問修飾符改為注冊類可訪問的修飾符,否則會注入失敗。

下面我們來看看使用效果:

咦,怎么會空引用呢?原因大概就是 Controller 是由Mvc 模塊管理的,不在 IOC 容器內,所以在 Controller 中無法使用 Autofac 注入的實例。

那為什么構造函數注入的時候又可以呢?大概或許可能他們都是構造函數注入吧...

為什么是大概呢?因為我暫時也沒有具體去深入研究到底是什么原因導致的,如果有一天,我想起來去研究了并且有結果了,我會在這里補上。

我們先解決上面的問題先,在 Startup 的 ConfigureServices 方法底部加入如下代碼:

// 使用 ServiceBasedControllerActivator 替換 DefaultControllerActivator;
// Controller 默認是由 Mvc 模塊管理的,不在 Ioc 容器中。替換之后,將放在 Ioc 容器中。
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

然后回到我們的AutofacModuleRegister 注入 Controller:

builder.RegisterTypes(GetAssemblyTypes<Startup>(type => typeof(ControllerBase).IsAssignableFrom(type)))
                .PropertiesAutowired();

這樣處理完后,屬性注入就Ok了。

存儲并提取容器實例

我們在之前項目的基礎上添加兩個項目 Common 與 Entities,存放公共類與實體類。

我們需要在實體類里面使用到 Common 項目中的某個類,結構如下:

// 基類實體   public class BaseEntity
    {
        public Class1 common_Class1 { get; set; }

        public string CreateId { get; set; }

        public void Create()
        {
            this.CreateId = common_Class1.getCurrentUserId();
        }
    }
    // 公共類
    public class Class1
    {
        public string getCurrentUserId()
        {
            return Guid.NewGuid().ToString();
        }
    }

從上面的接口中我們可以看到,我需要將 Class1 通過屬性注入到容器中:

builder.RegisterType<Class1>().PropertiesAutowired().InstancePerLifetimeScope();

我們先在 Controller 中看看效果:

public Class1 class1 { get; set; }

[HttpGet]
public string Autofac()
{
    return class1.getCurrentUserId();
}

很顯然結果是沒問題的:

那我們再到 BaseEntity 中去試試看:

咦,又出現空引用,注入失敗了。其實這個問題很明顯,我們使用的是 new 來實例化的 BaseEntity對象,沒有遵循容器實例使用規(guī)則,自然就無法使用容器中的實例了。

大家可以自己試一下,將 new 改為屬性注入就沒問題了,但是這種方案并不友好,下面要說的是另一種方案。

我們再新添加一個公共類:ContainerHelper,并聲明一個屬性用來存儲容器的實例:

public static class ContainerHelper
{
    public static ILifetimeScope ContainerBuilder { get; set; }
}

然后回到 Startup 中,在Configure 方法的底部加入如下代碼:

ContainerHelper.ContainerBuilder = app.ApplicationServices.CreateScope().ServiceProvider.GetAutofacRoot();

再回到實體類中去使用:

public void Create()
{
    if (common_Class1 == null)
    {
        using (var scope = ContainerHelper.ContainerBuilder.BeginLifetimeScope())
        {
            common_Class1 = scope.Resolve<Class1>();
        }
    }
    this.CreateId = common_Class1.getCurrentUserId();
}

Autofac 的替換方案暫時就寫到這里了,后續(xù)如果有新的理解或心得會再做修改,淺談嘛就真的是淺談,有錯誤或補充的地方請大家不吝賜教。

源碼這里就不提供了,大家有耐心的可以跟著手敲一遍,雖然對理解沒啥作用,但能使記憶更深刻一點。

到此這篇關于.Net Core中使用Autofac替換自帶的DI容器的示例的文章就介紹到這了,更多相關.Net Core Autofac替換DI容器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • .NET數組使用中的注意事項小結

    .NET數組使用中的注意事項小結

    這篇文章主要介紹了.NET數組使用中的注意事項,總結了常見的三個數組使用中的注意事項,對于.NET初學者有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • asp.net core集成JWT的步驟記錄

    asp.net core集成JWT的步驟記錄

    這篇文章主要給大家介紹了關于asp.net core集成JWT的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用asp.net core具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-06-06
  • asp.net下將頁面內容導入到word模板中的方法

    asp.net下將頁面內容導入到word模板中的方法

    asp.net下將頁面內容導入到word模板中的方法,需要的朋友可以參考下。
    2010-10-10
  • .Net Winform 實現CSS3.0 潑墨畫效果(示例代碼)

    .Net Winform 實現CSS3.0 潑墨畫效果(示例代碼)

    這篇文章主要介紹了.Net Winform 實現CSS3.0 潑墨畫效果,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2024-12-12
  • asp.net c#采集需要登錄頁面的實現原理及代碼

    asp.net c#采集需要登錄頁面的實現原理及代碼

    當我們采集頁面的時候,如果被采集的網站需要登錄才能采集,原理搞清楚了,就好辦了,我們所要做的僅僅是在采集的時候(或者說HttpWebRequest提交數據的時候),將Cookie信息放入Http請求頭里面就可以了,感興趣的朋友可以了解下,或許對你有所幫助
    2013-02-02
  • C#多線程Singleton(單件)模式模板

    C#多線程Singleton(單件)模式模板

    下面是一個C#多線程單件模式的代碼模板。把T換成你自己的類型就可以使用了。其精妙之處就在于用lock語句鎖定資源來避免多線程同時走入if語句去創(chuàng)建多個對象
    2012-02-02
  • ASP.NET 路徑問題的解決方法

    ASP.NET 路徑問題的解決方法

    相對路徑和絕對路徑在ASP.NET中可以用~/來解決.
    2009-06-06
  • vs2017軟鏈接失效而導致無法進入安裝界面的解決方法

    vs2017軟鏈接失效而導致無法進入安裝界面的解決方法

    這篇文章主要為大家詳細介紹了vs2017軟鏈接失效而導致無法進入安裝界面的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • .NET的強類型字符串(Strongly typed string)詳解

    .NET的強類型字符串(Strongly typed string)詳解

    強類型字符串是一種編譯時類型檢查的字符串表示方法,類似于枚舉,但具有更好的擴展性和約束性,強類型字符串可以提供更好的可讀性和維護性,并且可以避免運行時錯誤,本文介紹什么是.NET的強類型字符串(Strongly typed string),感興趣的朋友一起看看吧
    2024-12-12
  • Asp.net MVC中Razor常見的問題與解決方法總結

    Asp.net MVC中Razor常見的問題與解決方法總結

    這篇文章主要給大家介紹了關于Asp.net MVC中Razor常見的問題與解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面跟著小編來一起學習學習吧。
    2017-08-08

最新評論

婺源县| 拜泉县| 广州市| 龙门县| 潞城市| 鞍山市| 中山市| 抚松县| 青川县| 财经| 内江市| 清水县| 钟山县| 潮安县| 中江县| 通山县| 密云县| 囊谦县| 隆德县| 白河县| 房山区| 岳池县| 明溪县| 洛川县| 那曲县| 朝阳市| 神农架林区| 固始县| 彝良县| 思茅市| 隆昌县| 闻喜县| 江阴市| 长阳| 都匀市| 大关县| 东港市| 富川| 万荣县| 遵义市| 高要市|