Как внедрить Сервис в класс (не компонент)
Я хочу добавить сервис в класс, который не является компонентом.
Например
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 (перед тем, как он будет введен в первый раз).
- Альтернативный подход заключается в настройке настраиваемого инжектора типа
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
при создании экземпляра.
См. Также Взаимодействие с инжектором вручную внутри директивы
- Еще один способ - создать экземпляр самостоятельно:
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
}