Microsoft.Framework.DependencyInjection.Ninject
The project contains a total of 5 classes of files, the underlying use of ninject implementation of dependency injection, the project is as follows:
As you can see from the file name,ninjectserviceprovider and ninjectservicescopefactory are interface IServiceProvider and The implementation class of the iservicescopefactory .
( The implementation class of the Iservicescope interface acts as ninjectservicescopefactory Internal classes exist, not as separate files. )
The entrance to the project is still the Ninjectregistration class at the end of the registration.
Ninjectregistration
The file code is as follows
Public Static classninjectregistration { Public Static voidPopulate ( ThisIkernel Kernel, ienumerable<servicedescriptor>descriptors) {kernel. Load (NewServiceproviderninjectmodule (descriptors)); } Public StaticIbindingnamedwithoronsyntax<t> inrequestscope<t>( ThisIbindingwheninnamedwithoronsyntax<t>binding) { returnBinding. InScope (context =context. Parameters.getscopeparameter ()); } Internal StaticScopeparameter Getscopeparameter ( ThisIenumerable<iparameter>parameters) { return( scopeparameter) (parameters. Where (P= = P.name = =typeof(Scopeparameter). FullName). Singleordefault ()); } Internal StaticIenumerable<iparameter>Addorreplacescopeparameter ( ThisIenumerable<iparameter>parameters, Scopeparameter scopeparameter) { returnparameters. Where (P= = P.name! =typeof(Scopeparameter). FullName). Concat (New[] {scopeparameter}); } }
static method:
Populate: The role is to register Serviceproviderninjectmodule in the kernel. For Ninject Most of the time, a custom inherited from the Ninjectmodule class is registered to the kernel, and the inherited class is used to manage dependency injection.
Getscopeparameter: Get parameters of all "scopeparameter" types
Addorreplacescopeparameter: Gets all the "scopeparameter" parameters and replaces it with the incoming "Scopeparameter".
Inrequestscope: In "binding." InScope "To add" Scopeparameter ".
In general, the file is an auxiliary method and an externally initialized interface.
Serviceproviderninjectmodule
The file code is as follows:
Internal classServiceproviderninjectmodule:ninjectmodule {Private ReadOnlyIenumerable<servicedescriptor>_servicedescriptors; PublicServiceproviderninjectmodule (IEnumerable<ServiceDescriptor>servicedescriptors) {_servicedescriptors=servicedescriptors; } Public Override voidLoad () {foreach(varDescriptorinch_servicedescriptors) {Ibindingwheninnamedwithoronsyntax<Object>binding; if(Descriptor. Implementationtype! =NULL) {Binding=Bind (Descriptor. servicetype). to (descriptor. Implementationtype); } Else if(Descriptor. Implementationfactory! =NULL) {Binding= Bind (descriptor. servicetype). Tomethod (context = { varServiceProvider = context. Kernel.get<iserviceprovider>(); returnDescriptor. Implementationfactory (serviceprovider); }); } Else{Binding=Bind (Descriptor. servicetype). Toconstant (descriptor. Implementationinstance); } Switch(descriptor. Lifetime) { CaseServiceLifetime.Singleton:binding. Insingletonscope (); Break; CaseServiceLifetime.Scoped:binding. Inrequestscope (); Break; CaseServiceLifetime.Transient:binding. Intransientscope (); Break; }} Bind<IServiceProvider> (). Tomethod (context = { varResolver = context. Kernel.get<iresolutionroot>(); varInheritedparams = context. Parameters.where (p =P.shouldinherit); varScopeparam =NewScopeparameter (); Inheritedparams=Inheritedparams.addorreplacescopeparameter (Scopeparam); return NewNinjectserviceprovider (resolver, Inheritedparams.toarray ()); }). Inrequestscope (); Bind<IServiceScopeFactory> (). Tomethod (context = { return Newninjectservicescopefactory (context); }). Inrequestscope (); } }
View Code
Although the amount of code is relatively small, the internal logic is simple.
First, by convention, the ienumerable<servicedescriptor> type parameter that represents the dependency injection relationship is passed in.
The Load method is then overloaded, and the dependency injection relationship is initialized according to Ienumerable<servicedescriptor> when the kernel is called.
The Load method first iterates through the ienumerable<servicedescriptor> for each Servicedescriptor object, by implementing the class type, implementing the class factory, implementing the order of the class instance, and then setting the corresponding life cycle. The last injected IServiceProvider is Ninjectserviceprovider, Iservicescopefactory is the ninjectservicescopefactory type.
* It is important to note that the Ninjectserviceprovider and Ninjectservicescopefactory injection range is scope, And the Scopeparam parameter is replaced for each ninjectserviceprovider to guarantee its scope range.
Ninjectserviceprovider
Internal classNinjectserviceprovider:iserviceprovider {Private Static ReadOnlyMethodInfo _getall; Private ReadOnlyIresolutionroot _resolver; Private ReadOnlyiparameter[] _inheritedparameters; Private ReadOnly Object[] _getallparameters; StaticNinjectserviceprovider () {_getall=typeof(resolutionextensions). GetMethod ("GetAll",NewType[] {typeof(Iresolutionroot),typeof(iparameter[])}); } PublicNinjectserviceprovider (iresolutionroot resolver, iparameter[] inheritedparameters) {_resolver =Resolver; _inheritedparameters=inheritedparameters; _getallparameters=New Object[] {resolver, inheritedparameters}; } Public ObjectGetService (Type type) {returnGetsingleservice (type)??GetLast (GetAll (type))??getmultiservice (type); } Private Objectgetsingleservice (type type); PrivateIEnumerable Getmultiservice (Type collectiontype); PrivateIEnumerable GetAll (type type); Private Static ObjectGetLast (IEnumerable services); }
The class first initializes a static constructor when the class file is loaded, and the generic extension method "Ienumerable<t> getall<t> (this iresolutionroot root, params iparameter[] Parameters) "is assigned to the internal variable" _getall ". After the class constructor is initialized, the constructor assigns a value of Iresolutionroot _resolver (the inner core control class that relies on injection), iparameter[] _inheritedparameters assignment, and is "_getall" The parameters of the _getallparameters are initialized.
The system calls the GetService (Type) method when the system obtains an instance of the implementation class.
- The system first calls getsingleservice[internal for _resolver. Tryget (Type, _inheritedparameters)], gets the implementation of the simple type.
- Gets the data for the generic type, if the simple type is empty. Replace the T-type of the GetAll method with the actual type, then get all instances of that type, and finally go to the last of all instances.
Private IEnumerable GetAll (type type) { var getAll = _getall.makegenericmethod (type); return (IEnumerable) Getall.invoke (null, _getallparameters); }
- If all instances of this type are still empty, then the type of type may be ienumerable<t> type, then the type T is obtained, and the GetAll method is called.
Ninjectservicescopefactory and Ninjectservicescope
Here both classes inherit from Iservicescopefactory and Iservicescope.
Ninjectservicescopefactory only created the Ninjectservicescope object internally, the code is as follows:
Public ninjectservicescopefactory (IContext context) { = context. Kernel.get<iresolutionroot>(); = Context. Parameters.where (p = p.shouldinherit); } Public iservicescope createscope () { returnnew ninjectservicescope (_resolver, _inheritedparameters); }
Within Ninjectservicescope, each time a Ninjectserviceprovider instance is built with the new Scopeparameter parameter to ensure that a new scope is opened each time. The code is as follows:
Public ninjectservicescope ( iresolutionroot Resolver, IEnumerable<IParameter> Inheritedparameters) { new scopeparameter (); = Inheritedparameters.addorreplacescopeparameter (_scope); New Ninjectserviceprovider (resolver, Inheritedparameters.toarray ()); }
*addorreplacescopeparameter when the Scopeparameter type parameter is present, it is replaced with _scope, which is not present when it is added.
[ASP. 5] Dependencyinjection Project Code Analysis 3-ninject