简体   繁体   中英

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

I am trying to understand Dependency Injection where usually everything is injected as either via Constructor or Property Injection.

So far I have understood that it basically revolves around interface to mock the class.

I am checking out Nop Commerce where I came across CustomerModelFactory which accepts couple of Domain class like CustomerSettings , DatetimeSettings etc..

Now when I check the DependencyRegistrar.cs class, I don't see how the dependency registration or even in the same class, I don't see the new instance of CustomerSettings created anywhere.

So my question is when we inject concrete class in constructor of class, where do we register it or how IOC container supply the instance?

CustomerModelFactory.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,
    }

DependencyRegistrar.cs

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

I couldn't find where below is done:

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

How can I understand how this is working?

That's why DI does not really reduce complexity, instead, it hides complexity under surface and offload lifecycle management to another thing that you don't really know too much, as each DI framework is different. Anyway, that is another topic.

Here is to answer your question, ignore which DI framework, just think in general, there are 3 ways for you to get an instance of an object

  1. Create the instance directly when you need it
CustomerSettings settings = new CustomerSettings();
  1. Create the instance by Reflection when you need it
Type t = typeof(CustomerSettings);
CustomerSettings settings = Activator.CreateInstance(t) as CustomerSettings;
  1. Cache all instances in a dictionary and look up when using the type name

something can be like this:

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

(This way does not generate a new instance though). Now if you need the instance, you ask the dictionary to give it to you

lookup[typeof(CustomerSettings)]

This action, is called Resolved in many DI framework.


How does the DI framework find it though?

To do this, many DI framework will use reflection to find the matching type. There should always a process to register the types you want DI framework to resolve automatically. It means, you tell DI framework what type it needs to be aware, and then give it back to me when you look up using the type.

For example, you may see code like this:

container.Register<CustomerSettings>(); 

In this case, CustomerSettings is a class type, so DI knows how to create it when you need it.

However, if you are registering an interface

container.Register<ICustomerSettings, CustomerSettings>(): 

The above is one syntax to register interface and its concrete type. Basically, you tell DI, this is the type, and that is the implementation. So when you do this:

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

You will get an instance of CustomerSettings .

It will work if you have multiple implementations of the same interface, but you need some special handling. Different DI handles it differently.

Hopefully so far it makes a little sense.

Each DI framework has an IOC container, which acts like a dictionary. You register the type into there, and ask it to give it back.

There are more details, but I will not cover in here.

Concrete types are not automatically resolved by MS.DI; they need to be registered explicitly. NopCommerce, therefore, registers them inside its DependencyRegistrar class (on line 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;
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM