कंस्ट्रक्टर इंजेक्शन के बिना सेवा का उदाहरण प्राप्त करना


81

मेरे पास @Injectableबूटस्ट्रैप में परिभाषित एक सेवा है। मैं कंस्ट्रक्टर इंजेक्शन का उपयोग किए बिना सेवा का उदाहरण प्राप्त करना चाहता हूं। मैं का उपयोग करने की कोशिश की, ReflectiveInjector.resolveAndCreateलेकिन लगता है कि एक नया उदाहरण बनाने के लिए।

मैं जो करने की कोशिश कर रहा हूं उसका कारण मेरे पास कई घटकों द्वारा प्राप्त एक आधार घटक है। अब मुझे एक सेवा का उपयोग करने की आवश्यकता है लेकिन मैं इसे ctor में नहीं जोड़ना चाहता क्योंकि मैं इस सेवा को सभी व्युत्पन्न घटकों पर इंजेक्ट नहीं करना चाहता।

TLDR: मैं एक की जरूरत है ServiceLocator.GetInstance<T>()

अद्यतन: आरसी 5 के लिए अद्यतन कोड +: घटकों में उपयोग के लिए इंजेक्टर इंस्टेंस का भंडारण

जवाबों:


72

हां, ReflectiveInjector.resolveAndCreate()एक नया और असंबद्ध इंजेक्टर उदाहरण बनाता है।

आप Angulars Injectorइंस्टेंस को इंजेक्ट कर सकते हैं और इसका उपयोग करके वांछित उदाहरण प्राप्त कर सकते हैं

constructor(private injector:Injector) {
  injector.get(MyService);
}

आप Injectorकुछ वैश्विक वैरिएबल में भी स्टोर कर सकते हैं और इस इंजेक्टर इंस्टेंस का उपयोग करके उदाहरण के लिए उपलब्ध उदाहरण प्राप्त कर सकते हैं जैसे कि https://github.com/angular/angular/issues/4112#issuecomment-153811572 में बताया गया है


1
Bootstrap.then () में वैश्विक वैरिएबल में स्टोरिंग इंजेक्टर जैसा लगता है कि मुझे क्या चाहिए।
dstr

65
प्रश्न एक निर्माता के बिना कहता है जो इस जवाब को अनपेक्षित बनाता है।
जोनाथन माइल्स

1
यदि कंस्ट्रक्टर एक घटक में है, तो यह घटक इंजेक्टर है, एक सेवा में यह मॉड्यूल इंजेक्टर है (मूल रूप से रूट इंजेक्टर यदि यह एक आलसी लोडेड मॉड्यूल नहीं है)। आप जोड़कर मूल घटक इंजेक्टर भी प्राप्त कर सकते हैं @SkipSelf()parentरूट इंजेक्टर प्राप्त करने के लिए, आप गेट्टर को भी इंटर कर सकते हैं ।
गुंटर ज़ोचबॉयर

2
@ क्यों जादू? आप इंजेक्टर को एक स्थिर क्षेत्र या वैश्विक चर में साझा कर सकते हैं और इसे वहां से एक्सेस कर सकते हैं, लेकिन पहले आपको एक कंस्ट्रक्टर का उपयोग करके इसे "कहीं और" इंजेक्ट करने की आवश्यकता है और इसे स्थिर फ़ील्ड में असाइन करें।
गुंटर Zöchbauer

1
क्या डीआई कंटेनर एनजी उस खराब का उपयोग करता है, कि यह एक आम डीआई कंटेनर की बुनियादी सुविधाओं का भी समर्थन नहीं करता है?
रिहायस

61

अद्यतन किए गए कोणीय में जहाँ ngModules का उपयोग किया जाता है, आप कोड में कहीं भी उपलब्ध एक चर बना सकते हैं:

export let AppInjector: Injector;

export class AppModule {
  constructor(private injector: Injector) {
    AppInjector = this.injector;
  }
}

अब, आप AppInjectorअपने कोड में कहीं भी किसी भी सेवा को खोजने के लिए उपयोग कर सकते हैं ।

import {AppInjector} from '../app.module';

const myService = AppInjector.get(MyService);

1
अच्छा लगा। पर एक अच्छा जवाब हो सकता है stackoverflow.com/questions/39409328/... रूप में अच्छी तरह।
अर्जन

1
तुम राजा हो!
डेविड पेरोजी

वाह क्या हमें ऐसा करने की अनुमति है?
सिमोन_विवर

2
यह एक छोटी सी समस्या है। आपको आलसी लोड किए गए मॉड्यूल के लिए अलग-अलग इंजेक्टर बनाने होंगे जो एक सेवा प्रदान करते हैं।
वाहिद

7

एक अन्य दृष्टिकोण में एक कस्टम डेकोरेटर को परिभाषित करना शामिल है ( CustomInjectableनिर्भरता इंजेक्शन के लिए मेटाडेटा सेट करने के लिए:

export function CustomComponent(annotation: any) {
  return function (target: Function) {

    // DI configuration
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    var parentAnnotations = Reflect.getMetadata('design:paramtypes', parentTarget);

    Reflect.defineMetadata('design:paramtypes', parentAnnotations, target);

    // Component annotations / metadata
    var annotations = Reflect.getOwnMetadata('annotations', target);
    annotations = annotations || [];
    annotations.push(annotation);
    Reflect.defineMetadata('annotations', annotations, target);
  }
}

यह अपने स्वयं के बजाय मूल निर्माता से मेटाडेटा का लाभ उठाएगा। आप इसे बच्चे की कक्षा में उपयोग कर सकते हैं:

@Injectable()
export class SomeService {
  constructor(protected http:Http) {
  }
}

@Component()
export class BaseComponent {
  constructor(private service:SomeService) {
  }
}

@CustomComponent({
  (...)
})
export class TestComponent extends BaseComponent {
  constructor() {
    super(arguments);
  }

  test() {
    console.log('http = '+this.http);
  }
}

अधिक विवरण के लिए यह प्रश्न देखें:


2
समस्या यह है कि tsc मुझे सुपर (आर्ग्युमेंट्स) नहीं बताता है क्योंकि बेस कंस्ट्रक्टर के लिए तर्क मेल नहीं खाते हैं।
संसद

1
कि विशेष मामले में हम सिर्फ व्युत्पन्न वर्ग से निर्माता को हटा सकते हैं github.com/Microsoft/TypeScript/issues/12439
slowkot

-1

StoreService .ts

  import { Injectable} from '@angular/core';

    @Injectable()
    export class StoreService {
      static isCreating: boolean = false;
      static instance: StoreService ;

      static getInstance() {
        if (StoreService.instance == null) {
          StoreService.isCreating = true;
          StoreService.instance = new StoreService ();
          StoreService.isCreating = false;
        }
        return StoreService.instance;
      }
      constructor() {
        if (!StoreService.isCreating) {
          throw new Error('You can\'t call new in Singleton instances! Call StoreService.getInstance() instead.');
        }
     }

  MyAlertMethod(){
    alert('hi);
    }
  }

घटक

//call this service directly in component.ts as below:-

 StoreService.getInstance().MyAlertMethod();

यह उन सेवाओं के साथ कैसे काम कर सकता है जिनके लिए कंस्ट्रक्टर में अन्य सेवाओं की आवश्यकता होती है?
एमेके अजेह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.