第四十一節:再探依賴注入(coreMvc/應用啓動/控制檯)和多項目框架集成(原生反射、AutoFac集成新寫法)

一. 再探依賴注入

其它詳細用法參考之前的博客:https://www.cnblogs.com/yaopengfei/p/10754397.html  
                                               https://www.cnblogs.com/yaopengfei/p/12664400.html
官網:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-6.0

1. coreMvc中注入

    直接在Program中注入即可, 可以以接口的形式注入,也可以直接注入類

//1. 普通注入
builder.Services.AddScoped<IUserInfo, UserInfo>();
builder.Services.AddScoped<RoleInfo>();

    使用的時候在控制器中通過構造函數注入即可,代碼略。

2. 在應用啓動中解析

 (即在program中要使用,這裏是解析使用,註冊使用的還是1中的註冊)

 (1). 通過 var serviceScope = app.Services.CreateScope()

 (2). 通過GetRequiredService方法進行對象的解析

var app = builder.Build();

//2.在應用啓動中解析使用(使用的還是1中的普通注入)
using (var serviceScope = app.Services.CreateScope())
{
    var services = serviceScope.ServiceProvider;
    var userInfo = services.GetRequiredService<IUserInfo>();
    var roleInfo = services.GetRequiredService<RoleInfo>();
    Console.WriteLine("------------------測試在應用啓動中解析使用------------------------------");
    Console.WriteLine(userInfo.GetInfo());
    Console.WriteLine(roleInfo.GetInfo());
}

3.直接在控制檯中使用

 直接註冊+解析

 需要依賴【 Microsoft.Extensions.DependencyInjection】程序集,詳見下面代碼

             //3. 測試控制檯中使用
            {
                var serviceCollection = new ServiceCollection();
                serviceCollection.AddSingleton<IUserInfo, UserInfo>();
                var serviceProvider = serviceCollection.BuildServiceProvider();
                IUserInfo userService = serviceProvider.GetRequiredService<IUserInfo>();

                //下面是使用
                var result = userService.GetInfo();
            }

 

二. 多項目框架集成

1. 需求

  有多個項目, Ypf.Service、Ypf.IService、03-CoreMvcDI三個項目, 其中CoreMvcDI添加對Ypf.Service的引用,然後把Ypf.Service項目的輸出路徑改爲 【..\03-CoreMvcDI\bin\】

  想把Ypf.Service中所有實現ISupport接口的類註冊個他的實現接口

  [FromServices] IInfo2 _info2 是註冊失敗的,因爲沒有實現ISupport接口 (需要加上以後再測試一下哦)

特別注意:這裏的輸出路徑改爲 Ypf.Service項目的輸出路徑改爲 【..\03-CoreMvcDI\bin\】,利用合併文件夾的原則實現!!!  因爲Ypf.Service項目也會生成一個Debuger文件夾

2. 原生反射寫法

(和之前Core5.0中的寫法基本一致)

(1). 拼接dll的路徑,通過反射進行加載

(2). 獲取該dll中的符合條件的類(A.去掉抽象類 B.該類要實現ISupport接口)

(3). 遍歷類

   A. 拿到該類的所有接口(去掉ISupport接口)

   B. 遍歷接口,把該類註冊給所有實現的接口

代碼分享:

{

    var dirName = "03-Ypf.Service.dll";
    Assembly asmService = Assembly.LoadFile(AppContext.BaseDirectory + dirName);
    //抽象類不進行注入,沒有實現ISupport接口的類不進行注入
    var classList = asmService.GetTypes().Where(t => !t.GetTypeInfo().IsAbstract && typeof(ISupport).IsAssignableFrom(t)).ToList();
    foreach (Type serviceType in classList)
    {
        //把一個類註冊給它實現的全部接口(除了ISupport接口外)
        var interfaceTypes = serviceType.GetInterfaces().Where(t => t.Name != "ISupport").ToList();
        foreach (var interfaceType in interfaceTypes)
        {
            builder.Services.AddScoped(interfaceType, serviceType);
        }
    }

}

3. AutoFac集成新寫法

   和之前Core5.0的寫法有區別,詳見Program中的代碼

封裝MyAutoFacModule類
 public class MyAutoFacModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            {
                //這裏就是AutoFac的注入方式,下面採用常規的方式
                //詳見:https://www.cnblogs.com/yaopengfei/p/9479268.html
                //官網:https://autofac.org/

                //特別注意:其中很大的一個變化在於,Autofac 原來的一個生命週期InstancePerRequest,將不再有效。正如我們前面所說的,整個request的生命週期被ASP.NET Core管理了,
                //所以Autofac的這個將不再有效。我們可以使用 InstancePerLifetimeScope ,同樣是有用的,對應了我們ASP.NET Core DI 裏面的Scoped。

               //在普通類中配置文件的讀取麻煩,後面封裝(注:appsettings.json要改爲始終複製)
                var Configuration = new ConfigurationBuilder().AddJsonFile(AppContext.BaseDirectory + "appsettings.json").Build();
                var dirName = Configuration["IocDll"];
                Assembly asmService = Assembly.LoadFile(AppContext.BaseDirectory + dirName);

                builder.RegisterAssemblyTypes(asmService)
                       .Where(t => !t.IsAbstract && typeof(ISupport).IsAssignableFrom(t))  //只有實現了ISupport接口的類才進行註冊
                       .AsImplementedInterfaces()    //把一個類註冊給它實現的全部接口
                       .InstancePerLifetimeScope()   //作用域單例(比如Task.Run就是另外一個作用域),而非請求內單例(請求內單例用:InstancePerRequest)
                       .PropertiesAutowired();       //在core裏表示在注入類中實現構造函數注入
            }
        }
    }
program中的代碼(和5.0的寫法有區別了) 
    builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
    // Register services directly with Autofac here. Don't call builder.Populate(), that happens in AutofacServiceProviderFactory.
    builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new MyAutoFacModule()));
 
 

三. 老楊的開源框架

 

   https://github.com/yangzhongke/NETBookMaterials/tree/main/%E6%9C%80%E5%90%8E%E5%A4%A7%E9%A1%B9%E7%9B%AE%E4%BB%A3%E7%A0%81/YouZack-VNext/Zack.Commons


   主要分析RunModuleInitializers方法和ReflectionHelper.cs

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章