编程知识 cdmana.com

Angular11 source code exploration 9 [practical understanding of service source code]

angular-master\packages\core\src\di\interface\provider.ts

useClass


export interface ClassSansProvider {
  useClass: Type<any>;
}
export interface ClassProvider extends ClassSansProvider {
  /**
   * An injection token .( Usually ' Type ' or ' InjectionToken ' Example , But it can also be ' any 
   */
  provide: any;

  /**
   When it comes to true when , The injector returns an array of instances . This is very useful for allowing multiple 
    Providers span multiple files , Provide configuration information for a public token .
   */
  multi?: boolean;
}

useValue

export interface ValueSansProvider {
  /**
   *  Value to inject 
   */
  useValue: any;
}
export interface ValueProvider extends ValueSansProvider {
  provide: any;
  multi?: boolean;
}

useExisting

useExisting This means using a registered type to inject here ( Alias )

export interface ExistingSansProvider {
  /**
   * The existing “ token ” To return .( amount to “injector.get (useExisting)”)
   */
  useExisting: any;
}
export interface ExistingProvider extends ExistingSansProvider {
  provide: any;
  multi?: boolean;
}

useFactory

export interface FactorySansProvider {
  /**
   This function is called for “ token ” Create a value . Function called 
* It's solved ' token ' The value of the ' deps ' Field 
   */
  useFactory: Function;
    /*
    * Used as a ' useFactory ' The parameters of the function .
    */
  deps?: any[];
}
export interface FactoryProvider extends FactorySansProvider {
  provide: any;
  multi?: boolean;
}

Injector yes new An alternative to the operator , It can automatically parse

  • Constructor dependency .
  • In typical use , Application code requests dependencies in constructors , They are really made of Injector analysis .
 Parse an array of providers , And create an injector from these providers .

* The incoming provider can be an array 
* Or more providers of recursive arrays .
let injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
//  Get the first one 
let car = injector.get(Car);
 A process of flattening multiple nested arrays and converting individual arrays 
 take providers Convert to array 
    @Injectable()
     class Engine {
    }
    @Injectable()
    class Car {
      constructor(public engine:Engine) {}
    }
let providers = ReflectiveInjector.resolve([Car, [[Engine]]]);
providers.length  //2
providers[0].key.displayName    // "Car"
providers[1].key.displayName   // "Engine"
* Create the injector from the provider that was parsed before .
*
* Ben API Is a recommended method for constructing fuel injectors in performance sensitive components .
var providers = ReflectiveInjector.resolve([Car, Engine]);
var injector = ReflectiveInjector.fromResolvedProviders(providers);
injector.get(Car)  // Car
 Parse an array of providers , And create a sub injector from these providers .
var parent = ReflectiveInjector.resolveAndCreate([ParentProvider]);
var child = parent.resolveAndCreateChild([ChildProvider]);
child.get(ParentProvider) instanceof ParentProvider  //true
child.get(ChildProvider) instanceof ChildProvider // true
//  It's a bull's-eye    Son looking for father   ===  Always looking for my father 
child.get(ParentProvider)  //  parent.get(ParentProvider)
  • When DI analysis Providers when , It's going to be for every provider Standardize , That's to say, convert to standard form
function _normalizeProviders(
    providers: Provider[], res: NormalizedProvider[]): NormalizedProvider[] {
  providers.forEach(b => {
    if (b instanceof Type) {
      res.push({provide: b, useClass: b} as NormalizedProvider);

    } else if (b && typeof b == 'object' && (b as any).provide !== undefined) {
      res.push(b as NormalizedProvider);

    } else if (Array.isArray(b)) {
          //  If it's an array , Recursive processing 
      _normalizeProviders(b, res);

    } else {
      throw invalidProviderError(b);
    }
  });

  return res;
}

In the development process, we may encounter problems like the following


@Injectable()
class Socket {
  constructor(private buffer: Buffer) { }
}

console.log(Buffer)  // undefined

@Injectable()
class Buffer {
  constructor(@Inject(BUFFER_SIZE) private size: Number) { }
}

console.log(Buffer)  // [Function: Buffer]

//  Error reported after operation 

So in the compilation phase 「 Variable and function declarations are automatically promoted , Function expressions don't automatically promote 」

If we want to solve the above problems , The simplest way to do this is to exchange the order of class definitions , Or you can use Angular Provided forward reference characteristic ,Angular By introducing forwardRef Let's use construct injection when , Use undefined dependent object types ,

Let's see. forwardRef principle

 Allow references to undefined references .
*
* for example ,' forwardRef ' For what we need to quote ' token ' Purpose 
DI declared , But not yet defined . It's also used in the creation of token
* The query has not been defined .

export function forwardRef(forwardRefFn: ForwardRefFn): Type<any> {
//  When calling  forwardRef  When the method is used , We're just  forwardRefFn  Function object , Added a private property __forward_ref__
  (<any>forwardRefFn).__forward_ref__ = forwardRef;
     //  And then I override the function  toString  Method 
  (<any>forwardRefFn).toString = function() {
    return stringify(this());
  };
  return (<Type<any>><any>forwardRefFn);
}

If the created service does not depend on other objects , Yes, you don't need to use @Injectable() Class decorator , But when the service needs to inject dependent objects into the constructor , You need to use @Injectable() Decorator , Because it's just a statement @Injectable() The service of this decorator can be injected into other services

The recommended practice is whether there are dependent objects or not , Use... When creating services @Injectable() Class decorator , So all services follow the same rules , Uniformity

版权声明
本文为[Landlord's cat]所创,转载请带上原文链接,感谢
https://cdmana.com/2020/12/20201225002757545J.html

Scroll to Top