Как внедрить Сервис в класс (не компонент)

Я хочу добавить сервис в класс, который не является компонентом.

Например

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 еще не создан).

Есть ли другой способ использования сервиса в классе (не компонент)? или неправильно, как я разрабатываю код (использовать службу в классе, а не компоненте)

Спасибо.

Ответы

Ответ 1

Инъекции работают только с классами, которые создаются путем инъекции зависимостей Angulars (DI).

  • Вам нужно
    • добавить @Injectable() в MyClass и
    • укажите MyClass как providers: [MyClass] в компоненте или NgModule.

Когда вы затем вставляете 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

Не прямой ответ на вопрос, но если вы читаете это ТАК по той причине, что я, это может помочь...

Допустим, вы используете ng2-translate и действительно хотите, User.ts класс User.ts имел его. Вы сразу же подумаете, чтобы использовать DI, чтобы сделать это, в конце концов, вы делаете Angular. Но, если задуматься над этим, вы можете просто передать его в свой конструктор или сделать его общедоступной переменной, которую вы установили из компонента (где вы, по-видимому, делали это, 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);
}

Надеюсь, это поможет тем, кто, как я, собирался написать намного сложнее в обслуживании кода, потому что иногда мы слишком умны =]

(ПРИМЕЧАНИЕ: причина, по которой вы можете захотеть установить переменную вместо того, чтобы делать ее частью вашего метода конструктора, заключается в том, что у вас могут быть случаи, когда вам не нужно использовать сервис, поэтому всегда требовать его передачи будет означать введение дополнительного импорта/код, который никогда не используется)

Ответ 3

Это вроде (очень) нахально, но я подумала, что поделюсь своим решением. Обратите внимание, что это будет работать только со службами Singleton (внедренными в корень приложения, а не в компонент!), Поскольку они живут столько же времени, сколько ваше приложение, и их всегда существует только один экземпляр.

Во-первых, к вашим услугам:

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

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

Тогда в любом классе:

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

Это решение хорошо, если вы хотите уменьшить помехи в коде и в любом случае не используете не-одиночные сервисы.

Ответ 4

Если ваши методы обслуживания являются чистыми функциями, простой способ решить эту проблему - использовать статические члены в вашем сервисе.

ваш сервис

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
  }
}

Ответ 5

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
}