<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      .NET 依賴注入深入詳解

      原為鏈接:http://www.rzrgm.cn/ysmc/p/18796964

      .NET 依賴注入深入詳解

      依賴注入(Dependency Injection, DI)是.NET Core .NET 5/6/7/8/9/10+中最重要的設計模式之一,下面我將從多個維度詳細解釋它的工作原理和使用方法。

      一、核心概念解析

      1. 什么是依賴?

      當一個類A需要類B才能正常工作時,我們就說類A"依賴"于類B。例如:

      public class OrderService
      {
          private readonly ILogger _logger; // OrderService依賴于ILogger
          
          public OrderService(ILogger logger)
          {
              _logger = logger;
          }
      }

      2. 傳統方式的問題

      沒有DI時,我們可能會這樣寫:

      public class OrderService
      {
          private readonly FileLogger _logger = new FileLogger(); // 直接創建具體實現
          
          // ...
      }

      這種方式的缺點:

      • 緊耦合:OrderService直接依賴FileLogger

      • 難以測試:無法輕松替換為測試用的Logger

      • 難以修改:如果要改用DatabaseLogger,需要修改OrderService代碼

      二、.NET DI 容器詳解

      1. 服務注冊方式

      在Program.cs/Startup.cs中有三種主要注冊方式:

      // 1. 注冊具體類型
      services.AddTransient<EmailService>();
      
      // 2. 注冊接口-實現映射
      services.AddScoped<IEmailService, SmtpEmailService>();
      
      // 3. 注冊現有實例
      var logger = new FileLogger();
      services.AddSingleton<ILogger>(logger);

      2. 生命周期詳解

      生命周期描述適用場景示例
      Transient 每次請求都創建新實例 輕量級、無狀態服務 工具類、DTO映射
      Scoped 同一請求內共享實例 需要請求上下文的服務 DbContext、用戶會話
      Singleton 整個應用生命周期一個實例 全局共享資源 配置、緩存、日志

       

       

       

      3. 高級注冊技巧

      // 注冊多個實現
      services.AddTransient<IMessageService, SmsService>();
      services.AddTransient<IMessageService, EmailService>();
      
      // 命名注冊
      services.AddTransient<IMessageService>("SMS", typeof(SmsService));
      
      // 泛型注冊
      services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
      
      // 委托工廠
      services.AddTransient<IService>(sp => 
          new Service(sp.GetRequiredService<IOtherService>()));

      三、注入方式大全

      1. 構造函數注入(最推薦)

      public class ProductController
      {
          private readonly IProductService _service;
          
          public ProductController(IProductService service)
          {
              _service = service; // 由DI容器自動注入
          }
      }

      2. 方法注入

      public class ReportGenerator
      {
          public void Generate(IReportFormatter formatter) 
          {
              // 使用方法參數注入
          }
      }

      3. 屬性注入(不推薦但某些場景需要,如blazor)

      public class NotificationService
      {
          [Inject] // 需要特定屬性標記
          public ILogger Logger { get; set; }
      }

      4. 從容器直接解析(應避免,但有時必要)

      var service = serviceProvider.GetRequiredService<IMyService>();

      四、實際應用場景

      1. 分層架構中的DI

      // 基礎設施層
      services.AddDbContext<AppDbContext>(options => 
          options.UseSqlServer(Configuration.GetConnectionString("Default")));
      
      // 應用層
      services.AddScoped<IOrderService, OrderService>();
      
      // 領域層
      services.AddTransient<IDomainEventDispatcher, DomainEventDispatcher>();
      
      // 表現層
      services.AddControllersWithViews();

      2. 選項模式(Options Pattern)

      // 注冊配置
      services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
      
      // 注入使用
      public class EmailService
      {
          private readonly EmailSettings _settings;
          
          public EmailService(IOptions<EmailSettings> options)
          {
              _settings = options.Value;
          }
      }

      3. 日志集成

      public class ProductService
      {
          private readonly ILogger<ProductService> _logger;
          
          public ProductService(ILogger<ProductService> logger)
          {
              _logger = logger; // 自動注入日志系統
          }
      }

      五、高級主題

      1. 第三方容器集成

      // Autofac示例
      builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
          .ConfigureContainer<ContainerBuilder>(builder =>
          {
              builder.RegisterModule(new MyAutofacModule());
          });

      2. 裝飾器模式

      // 原始服務
      services.AddScoped<IDataService, DataService>();
      
      // 裝飾器
      services.Decorate<IDataService, CachingDataService>();

      3. 驗證服務注冊

      // 檢查所有服務是否已注冊
      var provider = services.BuildServiceProvider();
      foreach (var service in services)
      {
          provider.GetRequiredService(service.ServiceType); // 會拋出異常如果未注冊
      }

      六、最佳實踐

      1. 構造函數保持簡單:只注入必要的依賴

      2. 避免服務定位器模式:不要濫用GetService

      3. 注意生命周期:避免Scoped服務被Singleton服務引用

      4. 使用接口:盡量依賴抽象而非具體實現

      5. 避免過度注入:如一個類注入超過5個服務,考慮重構

      七、常見問題解決

      循環依賴問題

      // 錯誤示例
      class A { public A(B b) {} }
      class B { public B(A a) {} }
      
      // 解決方案:
      // 1. 重構設計,提取公共邏輯到第三個類
      // 2. 使用屬性注入或方法注入替代構造函數注入

      多實現選擇

      // 注冊多個實現
      services.AddTransient<IMessageService, EmailService>();
      services.AddKeyedTransient<IMessageService, SmsService>("SMS");
      
      // 解析所有實現
      var services = provider.GetServices<IMessageService>();
      
      // 命名解析
      var smsService = provider.GetRequiredKeyedService<IMessageService>("SMS");

      感謝各位大佬的觀看!

      posted @ 2025-03-27 22:01  一事冇誠  閱讀(13273)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 综合偷自拍亚洲乱中文字幕| 人妻丰满熟妇无码区免费| 国产精品视频第一第二区| 激情综合网五月婷婷| 亚洲AV成人片在线观看| 香蕉影院在线观看| 国产综合视频一区二区三区| 亚洲av成人无码精品电影在线| 国产精品无码a∨麻豆| 亚洲中文字幕无码爆乳| 国内揄拍国产精品人妻电影| 午夜精品极品粉嫩国产尤物| 欧美日韩国产图片区一区| 国产精品久久无码不卡黑寡妇| 国产成人精品日本亚洲直播| 日韩精品福利一二三专区| 男女性杂交内射女bbwxz| 99riav国产精品视频| 亚洲午夜福利网在线观看| 久久免费看少妇免费观看| 亚洲欧洲一区二区精品| 撕开奶罩揉吮奶头视频| 国产精品亚洲一区二区z| 如皋市| 日韩精品国产二区三区| 亚洲色最新高清AV网站| 国产成人精彩在线视频50| 日韩精品一区二区都可以| 精品少妇后入一区二区三区| 国产初高中生粉嫩无套第一次| 绍兴市| 免费AV片在线观看网址| 国产精品自在自线免费观看| 午夜激情福利一区二区| 日韩伦理片| 亚洲精品久久久久成人2007| 精品人妻av综合一区二区| 亚洲av免费成人在线| 亚洲愉拍一区二区三区| 国产91精品一区二区蜜臀| 国产麻豆精品手机在线观看|