簡體   English   中英

在構造函數中注入的具體 class 在哪里注冊到 DI 框架?

[英]Where are concrete class injected in constructor being registered with DI framework?

我試圖了解依賴注入,通常所有東西都是通過構造函數或屬性注入注入的。

到目前為止,我了解到它基本上圍繞模擬 class 的接口。

我正在檢查 Nop Commerce,在那里我遇到了CustomerModelFactory ,它接受幾個域 class,如CustomerSettingsDatetimeSettings等。

現在,當我檢查DependencyRegistrar.cs class 時,我看不到依賴項注冊如何,甚至在同一個 class 中,我看不到在任何地方創建的CustomerSettings的新實例。

所以我的問題是,當我們在 class 的構造函數中注入具體的 class 時,我們在哪里注冊它或 IOC 容器如何提供實例?

客戶模型工廠.cs

 public partial class CustomerModelFactory : ICustomerModelFactory
    {
    // all below are concrete class
      public CustomerModelFactory(AddressSettings addressSettings,
            CaptchaSettings captchaSettings,
            CatalogSettings catalogSettings,
            CommonSettings commonSettings,
            CustomerSettings customerSettings,
            DateTimeSettings dateTimeSettings,
    }

依賴注冊器.cs

 public class DependencyRegistrar : IDependencyRegistrar
    {
       
        public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
        {
          builder.RegisterType<CustomerModelFactory>().As<ICustomerModelFactory>().InstancePerLifetimeScope();
    }
}

我找不到以下完成的位置:

CustomerSettings settings = new CustomerSettings();
    or
CatalogSettings settings = new CatalogSettings();

我如何理解這是如何工作的?

這就是為什么 DI 並沒有真正降低復雜性,而是將復雜性隱藏在表面之下,並將生命周期管理轉移到您不太了解的另一件事上,因為每個 DI 框架都是不同的。 無論如何,這是另一個話題。

這里是回答你的問題,忽略哪個DI框架,只是想一般,有3種方法可以讓你獲得一個object的實例

  1. 需要時直接創建實例
CustomerSettings settings = new CustomerSettings();
  1. 需要時通過反射創建實例
Type t = typeof(CustomerSettings);
CustomerSettings settings = Activator.CreateInstance(t) as CustomerSettings;
  1. 緩存字典中的所有實例,並在使用類型名稱時查找

可能是這樣的:

Dictionary<Type, object> lookup;
lookup.Add(typeof(CustomerSettings), new CustomerSettings()): 

(這種方式雖然不會生成新實例)。 現在,如果您需要實例,請讓字典將其提供給您

lookup[typeof(CustomerSettings)]

這個動作,在很多 DI 框架中被稱為Resolved


DI 框架是如何找到它的呢?

為此,許多 DI 框架會使用反射來查找匹配類型。 應該總是有一個過程來注冊您希望 DI 框架自動解析的類型。 這意味着,您告訴 DI 框架它需要知道什么類型,然后在您使用該類型查找時將其返回給我。

例如,您可能會看到如下代碼:

container.Register<CustomerSettings>(); 

在這種情況下, CustomerSettings是 class 類型,因此 DI 知道在需要時如何創建它。

但是,如果您正在注冊一個接口

container.Register<ICustomerSettings, CustomerSettings>(): 

以上是注冊接口及其具體類型的一種語法。 基本上,你告訴 DI,這是類型,這就是實現。 所以當你這樣做時:

var setting = container.Resolve<ICustomerSettings>();

您將獲得CustomerSettings的一個實例。

如果您有相同接口的多個實現,它將起作用,但您需要一些特殊處理。 不同的DI處理方式不同。

希望到目前為止它有點意義。

每個 DI 框架都有一個 IOC 容器,其作用類似於字典。 您將類型注冊到那里,並要求它返回。

還有更多細節,但我不會在這里介紹。

MS.DI 不會自動解析具體類型; 他們需要明確注冊。 因此,NopCommerce 在其DependencyRegistrar class 中注冊它們(第241行):

//register all settings
var settings = typeFinder.FindClassesOfType(typeof(ISettings), false).ToList();
foreach (var setting in settings)
{
    services.AddScoped(setting, serviceProvider =>
    {
        var storeId = DataSettingsManager.IsDatabaseInstalled()
            ? serviceProvider.GetRequiredService<IStoreContext>()
                 .GetCurrentStoreAsync().Result?.Id ?? 0
            : 0;

        return serviceProvider.GetRequiredService<ISettingService>()
            .LoadSettingAsync(setting, storeId).Result;
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM