कक्षा में सेवा इंजेक्ट कैसे करें (घटक नहीं)


91

मैं एक सेवा को एक वर्ग में इंजेक्ट करना चाहता हूं जो एक घटक नहीं है

उदाहरण के लिए:

MyService

import {Injectable} from '@angular/core';
@Injectable()
export class myService {
  dosomething() {
    // implementation
  }
}

मेरी कक्षा

import { myService } from './myService'
export class MyClass {
  constructor(private myservice:myService) {

  }
  test() {
     this.myservice.dosomething();
  }
}

यह समाधान काम नहीं करता है (मुझे लगता है कि क्योंकि MyClassअभी तक त्वरित नहीं किया गया है)।

क्या एक वर्ग में सेवा का उपयोग करने का एक और तरीका है (घटक नहीं)? या क्या आप मेरे कोड डिज़ाइन को अनुपयुक्त मानते हैं (एक वर्ग में एक सेवा का उपयोग करने के लिए जो एक घटक नहीं है)?

धन्यवाद।

जवाबों:


57

इंजेक्शन केवल उन वर्गों के साथ काम करते हैं जो अंगुलियों की निर्भरता इंजेक्शन (डीआई) द्वारा त्वरित होते हैं।

  1. आपको
    • जोड़ने @Injectable()के लिए MyClassऔर
    • एक घटक या NgModule में प्रदान करते MyClassहैं providers: [MyClass]

जब आप MyClassकहीं इंजेक्षन करते हैं, तो एक MyServiceउदाहरण पास हो जाता है MyClassजब यह DI द्वारा त्वरित किया जाता है (इससे पहले इसे पहली बार इंजेक्ट किया जाता है)।

  1. एक वैकल्पिक दृष्टिकोण जैसे कस्टम इंजेक्टर को कॉन्फ़िगर करना है
constructor(private injector:Injector) { 
  let resolvedProviders = ReflectiveInjector.resolve([MyClass]);
  let childInjector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, this.injector);

  let myClass : MyClass = childInjector.get(MyClass);
}

इस तरह myClassसे एक MyClassउदाहरण होगा, Angulars DI द्वारा त्वरित, और जब तत्काल myServiceकिया जाएगा MyClassतब इंजेक्शन लगाया जाएगा । एक निर्देश के अंदर मैन्युअल रूप से इंजेक्टर से निर्भरता प्राप्त करना
भी देखें

  1. फिर भी एक और तरीका है कि आप खुद ही उदाहरण प्रस्तुत करें:
constructor(ms:myService)
let myClass = new MyClass(ms);

2
मुझे लगता है कि एक स्टैंडअलोन वर्ग के लिए सेवा को इंजेक्ट करना एक विरोधी पैटर्न है।
tomexx

11
यकीन है, लेकिन कभी-कभी यह अभी भी समझ में आता है और यह जानना हमेशा अच्छा होता है कि क्या संभव है
गुंटर ज़ोचबॉयर

कंस्ट्रक्टर में नया इंजेक्टर क्यों बनाएं? इंजेक्शन का उपयोग क्यों नहीं किया गया था? यदि आप एक नया बनाने जा रहे हैं तो पहली बार में इंजेक्शन लगाने का कोई कारण नहीं है
smac89

नया अतिरिक्त प्रदाताओं के साथ एक बच्चा इंजेक्टर है। यदि चाइल्ड इंजेक्टर में जोड़े गए प्रदाता उन प्रदाताओं पर निर्भर करते हैं जो मूल घटकों या मॉड्यूल स्तर पर प्रदान किए जाते हैं, तो DI इसे सभी स्वचालित रूप से हल कर सकता है। इसलिए निश्चित रूप से ऐसे हालात हैं जहां यह समझ में आता है।
गुंटर ज़ोचबॉयर

1
@TimothyPenz संपादन के लिए धन्यवाद। इस उदाहरण में private, आवश्यक नहीं है, क्योंकि injectorकंस्ट्रक्टर के बाहर उपयोग नहीं किया जाता है, इसलिए किसी फ़ील्ड में संदर्भ रखने की आवश्यकता नहीं है।
गुंटर ज़ोचबॉयर

30

इस सवाल का सीधा जवाब नहीं है, लेकिन अगर आप इस कारण से एसओ को पढ़ रहे हैं तो मुझे मदद मिल सकती है ...

मान लीजिए कि आप एनजी 2-ट्रांसलेशन का उपयोग कर रहे हैं और आप वास्तव में चाहते हैं कि आपकी User.tsकक्षा में यह हो। आप तत्काल सोच रहे हैं कि इसे लगाने के लिए DI का उपयोग करना है, आप सब के बाद कोणीय कर रहे हैं। लेकिन यह उस पर हावी होने की तरह है, आप इसे केवल अपने कंस्ट्रक्टर में पारित कर सकते हैं, या इसे एक सार्वजनिक चर बना सकते हैं जिसे आपने घटक से निर्धारित किया है (जहां आपने निश्चित रूप से इसे DI किया है)।

उदाहरण के लिए:

import { TranslateService } from "ng2-translate";

export class User {
  public translateService: TranslateService; // will set from components.

  // a bunch of awesome User methods
}

तब कुछ उपयोगकर्ता-संबंधित घटक से जिसने TranslateService को इंजेक्ट किया

addEmptyUser() {
  let emptyUser = new User("", "");
  emptyUser.translateService = this.translateService;
  this.users.push(emptyUser);
}

उम्मीद है कि यह मेरी तरह उन लोगों की मदद करता है जो कोड को बनाए रखने के लिए बहुत कठिन लिखने वाले थे क्योंकि हम कभी-कभी बहुत चालाक होते हैं =]

(नोट: इसका कारण यह हो सकता है कि आप इसे अपने कंस्ट्रक्टर विधि का हिस्सा बनाने के बजाय एक चर सेट कर सकते हैं। क्या आपके पास ऐसे मामले हो सकते हैं, जहां आपको सेवा का उपयोग करने की आवश्यकता नहीं है, इसलिए हमेशा इसे पारित करने की आवश्यकता होती है, इसका मतलब अतिरिक्त आयात शुरू करना होगा। / कोड जो वास्तव में कभी उपयोग नहीं किए जाते हैं)


और शायद translateServiceएक मिल / सेट करें जहां getएक अशक्तता अपवाद के बजाय एक सार्थक त्रुटि फेंकता है यदि आप इसे सेट करना भूल गए हैं
शमौन_वेर

1
हो सकता है कि वर्ग रचनाकार में अनुवाद सेवा को एक आवश्यक परम बनाने के लिए यह अधिक समझ में आता है? यह पैटर्न DI पैटर्न imho के अनुरूप अधिक है।
इकाइकोल

16

यह एक तरह से ( बहुत ) हैकी है, लेकिन मुझे लगा कि मैं अपना समाधान भी साझा करूंगा। ध्यान दें कि यह केवल सिंगलटन सेवाओं (ऐप रूट पर इंजेक्शन, घटक नहीं!) के साथ काम करेगा , क्योंकि वे आपके आवेदन के रूप में लंबे समय तक रहते हैं, और उनमें से केवल एक उदाहरण है।

सबसे पहले, आपकी सेवा में:

@Injectable()
export class MyService {
    static instance: MyService;
    constructor() {
        MyService.instance = this;
    }

    doSomething() {
        console.log("something!");
    }
}

फिर किसी भी वर्ग में:

export class MyClass {
    constructor() {
        MyService.instance.doSomething();
    }
}

यह समाधान अच्छा है यदि आप कोड अव्यवस्था को कम करना चाहते हैं और वैसे भी गैर-सिंगलटन सेवाओं का उपयोग नहीं कर रहे हैं।


लेकिन आप कंस्ट्रक्टर में किसी भी घोषणा के बिना MyClass में MyService का उपयोग कैसे करते हैं?
अखिल वी

@AkhilV आप केवल MyService को आयात करते हैं क्योंकि आप किसी अन्य वर्ग को आयात करेंगे, फिर आप सीधे वर्णित विधि को कॉल कर सकते हैं।
Kilves

13

locator.service.ts

import {Injector} from "@angular/core";

export class ServiceLocator {
    static injector: Injector;
}

app.module.ts

@NgModule({ ... })

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

poney.model.ts

export class Poney {

    id: number;
    name: string;
    color: 'black' | 'white' | 'brown';

    service: PoneyService = ServiceLocator.injector.get(PoneyService); // <--- HERE !!!

    // PoneyService is @injectable and registered in app.module.ts
}

1
यह निश्चित नहीं है कि ओपी के परिदृश्य के लिए सबसे अच्छा अभ्यास क्या है, लेकिन यह उत्तर प्रमुख लोगों की तुलना में बहुत सरल लगता है। क्या injector.get()मॉड्यूल कार्य को कॉल को आगे बढ़ाएगा (कई सेवाओं को एक ही उदाहरण मानकर "साझा कर सकता है")?
G0BLiN

मुझे लगता है कि कोड सभी पॉनी इंस्टेंस द्वारा समाप्त हो जाएगा, जो पॉनी सेवा का एक ही उदाहरण साझा करता है। तुम क्या सोचते हो?
जूलियन

जूलियन - यह मेरे परिदृश्य के लिए एक स्वीकार्य परिणाम (वास्तव में पसंदीदा है) - एक इनपुट वैलिडेटर, उपयोगकर्ता अनुमतियाँ हैंडलर या स्थानीयकरण सेवा जैसे कुछ के बारे में सोचें - जहां आपको ऐप में समान कार्यक्षमता की आवश्यकता है लेकिन प्रत्येक के लिए एक अद्वितीय उदाहरण की आवश्यकता नहीं है सेवा के व्यक्तिगत उपभोक्ता।
G0BLiN

जसमाइन परीक्षणों में काम करने के लिए कुछ परेशानी होने की कोशिश कर रहा है। परीक्षण सेटअप को कॉन्फ़िगर कैसे करें? ServiceLocator.injector अशक्त लौटता रहता है, हालाँकि मैंने "PoneyService" को टेस्टबेड में इंजेक्ट किया है?
GGizmos

3

यदि आपकी सेवा विधियां शुद्ध कार्य हैं, तो इसे हल करने का एक साफ तरीका यह है कि आपकी सेवा में स्थिर सदस्य हों।

सेवा में

import {Injectable} from '@angular/core';
@Injectable()
export class myService{
  public static dosomething(){
    //implementation => doesn't use `this`
  }
}

आपकी कक्षा

export class MyClass{
  test(){
     MyService.dosomething(); //no need to inject in constructor
  }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.