当前位置:网站首页>Deep understanding of control inversion and dependency injection
Deep understanding of control inversion and dependency injection
2022-04-23 17:06:00 【begeneral】
I didn't quite understand these two concepts before , This period of time is learning ASP.NET CORE, and ASP.NET CORE It is based on the dependency injection framework , So I studied hard .
So called inversion of control , In fact, it is from active to passive . In the past, we had to new An object is very directly new, This is actually a violation of one of the most important principles of programming : Low coupling .
Because in A Class directly B Class causes A Is directly dependent on B Of , The scalability of the program designed in this way is very poor , This way we call it active .
What is passivity ? Passivity is A Class if you need to reference B class , Not in A Class B class , But provided by the framework B Class .
In this case , commonly B Class is inherited from an interface or abstract class ,A Class refers to an interface or abstract class , In this way, it conforms to the design principle of interface oriented programming ,A and B decoupling .
So when it comes to this , I'm sure you'll ask , How does the framework provide B Class instance ?
There are many ways , such as : Template method 、 Factory method 、 Abstract factory . The ideas of these methods are actually similar : Define an interface or abstract class C, Give Way B Inherit C, stay B To realize
Those abstract methods or virtual methods , I won't introduce this in detail .
Dependency injection is actually a framework for control inversion , Inversion of control is a design concept , Dependency injection is a framework to realize this idea , That's why their brothers are often
The reason for bringing it up together .
The popular explanation for dependency injection is : If A rely on B,B Inherit from interface or abstract class C, that A The reference in the class should be C, send A And B decoupling . How do you explain that ? In fact, when writing code
To configure C Implementation class of , After the program starts , The dependency injection framework will C and B The relationship is stored in a ServiceDescriptor Class , When A Need to use C when , The dependency injection framework will be based on B and C Instantiate a mapping relationship B Give to the A.
So it looks like , The name of dependency injection is quite appropriate, isn't it .
How does the dependency injection framework provide B Class instance ? Let's explain the internal implementation of the dependency injection framework from a purely theoretical point of view ( It's better to download ASP.NET CORE The source code of , In this way, you will understand in more detail )
The ways of dependency injection are 3 in : Constructor Injection 、 Attribute injection 、 Methods to inject . What we use most is constructor injection , Of course. ASP.NET CORE Of startup Class ConfigureServices and Configure Method injection is also used in the function .
Let's talk about the registration process of dependency injection first . Everyone knows that we call IServiceCollection Of Add Method to register the service (IServiceCollection There are several extension methods , You can add services with different life cycles , But it's all calls in the end Add Method ),
How does this framework store these registration information ? If you don't consider the details , In fact, it's quite simple . Is in the ServiceCollection(IServiceCollection The default implementation of the interface ) It defines List<ServiceDescriptor> Global variable of type ,
All parameters of a registered service are defined in ServiceDescriptor Class , such as : Service type (ServiceType)、 Implementation types (ImplementationType)、 Life cycle (Lifetime) Equal attribute . Every time you add a service registration , This List Just add a ServiceDescriptor.
Registration is over , Let's talk about the consumption of services , This is how the framework instantiates the corresponding instance .
Let's first talk about some conditions that the registered implementation class needs to meet . First, the implementation class must have a public constructor , Otherwise, how to instantiate ? Second, if the constructor has parameters , That parameter must be
The dependency injection framework must be able to provide , For example, this parameter is an interface or abstract class that has been registered to the framework .
This leads to 2 A question , Let's take a look at the code :
services.AddSingleton<IFoo, Foo>();
services.AddSingleton<IBar, Bar>();
services.AddSingleton<IQux, Qux>();
public class Qux:IQux
{
public Qux(IFoo foo)
{
Console.WriteLine($"Selected constructor:Qux(IFoo foo)");
}
public Qux(IFoo foo,IBar bar)
{
Console.WriteLine($"Selected constructor:Qux(IFoo foo,IBar bar)");
}
}
Qux Yes 2 Constructors , Which one will the dependency injection framework choose ? We are in the IQux Put it in the constructor of a controller , Run up and have a look :
The selected constructor is the second , This example shows that the parameters of the constructor must be a subset of all the parameters that the dependency injection framework can provide . If no matching parameter is found, an error will be reported .
Let's look at another situation :
public class Qux:IQux
{
public Qux(IFoo foo,IBar bar)
{
Console.WriteLine($"Selected constructor:Qux(IFoo foo,IBar bar)");
}
public Qux(IFoo foo,IBaz baz)
{
Console.WriteLine($"Selected constructor:Qux(IFoo foo,IBaz baz)");
}
}
services.AddSingleton<IFoo, Foo>();
services.AddSingleton<IBar, Bar>();
services.AddSingleton<IBaz, Baz>();
services.AddSingleton<IQux, Qux>();
In this case, this 2 Both constructors satisfy , The framework cannot choose the appropriate constructor , It's a direct error .
Combined with the life cycle , Let's think a little more , If Qux The life cycle of is Singleton,Foo The life cycle of is Scope, and Qux Refer to the Foo, What will happen then ?
services.AddScoped<IFoo, Foo>();
services.AddSingleton<IQux, Qux>();
public class Qux:IQux
{
public Qux(IFoo foo)
{
Console.WriteLine($"Selected constructor:Qux(IFoo foo)");
}
}
The running result is :
System.AggregateException:“Error while validating the service descriptor 'ServiceType: ValidateScope.IQux Lifetime: Singleton ImplementationType: ValidateScope.Qux': Cannot consume scoped service 'Vali”
It means that the life cycle is Singleton The type of Qux Cannot consume. The life cycle is Scope Of Foo. This is actually very easy to understand ,Singleton Services are stored in the root container , Is a singleton , Its life cycle is from the start of the program to the end of the program , Throughout the entire application lifecycle .
and Scope Services are sub containers stored under the root container , Its life cycle is from the beginning to the end of a request , If Singleton The service refers to Scope service , It's equivalent to putting Scope Service is put in Singleton Service went inside , But when you register, you register as Scope service , So this must be
Conflicting .
Let's talk about the creation process of service instance , Altogether 4 Create an instance of the service in the way :
1、RuntimeServiceProviderEngine, Provide service instances in a reflective way
2、ILEmitServiceProviderEngine, use IL Emit To provide service instances
3、ExpressionsServiceProviderEngine, Use expression tree to provide service instance
4、DynamicServiceProviderEngine, According to the number of concurrent requests, the final service instance provision scheme is determined dynamically
By default, the framework adopts the fourth method . In fact, I only know the way of reflection , Others don't know much , If you are interested, you can download it yourself ASP.NET CORE Study the source code of .
The above is my understanding of control inversion and dependency injection , If something is wrong , Please leave a message to correct , thank you !
版权声明
本文为[begeneral]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230554081905.html
边栏推荐
- Detailed explanation of information abstract, digital signature, digital certificate, symmetric encryption and asymmetric encryption
- Log4j output log information to file
- Do you really understand the principle of code scanning login?
- ◰ GL shadow map core steps
- Introduction to new functions of camtasia2022 software
- JSON deserialize anonymous array / object
- org. apache. parquet. schema. InvalidSchemaException: A group type can not be empty. Parquet does not su
- Promise (IV)
- 【WPF绑定3】 ListView基础绑定和数据模板绑定
- An essay on the classical "tear down the wall in thinking"
猜你喜欢
PyMySQL
How vscode compares the similarities and differences between two files
Nifi fast installation and file synchronization
ACL 2022 | dialogved: a pre trained implicit variable encoding decoding model for dialogue reply generation
STM32__03—初识定时器
Nodejs reads the local JSON file through require. Unexpected token / in JSON at position appears
Bytevcharts visual chart library, I have everything you want
STM32__ 03 - beginner timer
VLAN advanced technology, VLAN aggregation, super VLAN, sub VLAN
Modify the test case name generated by DDT
随机推荐
Smart doc + Torna generate interface document
Get the column name list of the table quickly in Oracle
Encapsulating the logging module
Nodejs reads the local JSON file through require. Unexpected token / in JSON at position appears
Collect blog posts
Paging the list collection
EF core in ASP Generate core priority database based on net entity model
El cascade and El select click elsewhere to make the drop-down box disappear
Preliminary understanding of promse
Deeply understand the relevant knowledge of 3D model (modeling, material mapping, UV, normal), and the difference between displacement mapping, bump mapping and normal mapping
Grpc gateway based on Ocelot
Production environment——
[pimf] openharmony paper Club - what is the experience of wandering in ACM survey
Solution architect's small bag - 5 types of architecture diagrams
. net type transfer
Promise (II)
1-3 nodejs installation list configuration and project environment
An essay on the classical "tear down the wall in thinking"
Decimal format decimal / datetime conversion processing
freeCodeCamp----prob_ Calculator exercise