Angular2 инъекция зависимостей, не вводящая услугу во время наследования класса
Я использую angular2
с Typescript
. Я пытаюсь создать base class
, который может быть унаследован другими классами, и в базовом классе вводится служба. До сих пор я не мог правильно получить ajaxService
injected
в base class
, который находится inherited
в user class
. В частности, когда создается экземпляр пользователя, а затем метод save()
вызывается из экземпляра user
, следующая строка в base class
: return _this._ajaxService.send(options);
не работает, поскольку _ajaxService
- undefined.
Вот user class
, который расширяет base class
:
import {Base} from '../utils/base';
export class User extends Base {
// properties
id = null;
email = null;
password = null;
first_name = null;
last_name = null;
constructor(source) {
_super.CopyProperties(source, this);
}
}
Вот base class
:
import {Component} from 'angular2/core';
import {AjaxService} from './ajax.service';
@Component({
providers: [AjaxService]
})
export class Base {
constructor(private _ajaxService: AjaxService) { }
// methods
public static CopyProperties(source:any, target:any):void {
for(var prop in source){
if(target[prop] !== undefined){
target[prop] = source[prop];
}
else {
console.error("Cannot set undefined property: " + prop);
}
}
}
save(options) {
const _this = this;
return Promise.resolve()
.then(() => {
const className = _this.constructor.name
.toLowerCase() + 's';
const options = {
data: JSON.stringify(_this),
url: className,
action: _this.id ? 'PATCH' : 'POST';
};
debugger;
return _this._ajaxService.send(options);
});
}
}
Это работает отлично, за исключением того, что ajaxService
не вводится в базовый класс. Я предполагаю, что это имеет смысл, поскольку пользователь создается не основанием.
Итак, как я могу использовать ajaxService
в Base module
, когда когда базовый модуль расширяется в другом классе?
Я думаю, когда я создаю экземпляр пользователя, вызывается конструктор в классе пользователя, но конструктор базового класса, который вводит эту услугу, не вызывается.
Здесь ajaxService
:
import {Injectable} from 'angular2/core';
@Injectable()
export class AjaxService {
// methods
send(options) {
const endpoint = options.url || "";
const action = options.action || "GET";
const data = options.data || {};
return new Promise((resolve,reject) => {
debugger;
$.ajax({
url: 'http://localhost:3000' + endpoint,
headers: {
Authentication: "",
Accept: "application/vnd.app.v1",
"Content-Type": "application/json"
},
data: data,
method: action
})
.done((response) => {
debugger;
return resolve(response);
})
.fail((err) => {
debugger;
return reject(err);
});
});
}
}
Ответы
Ответ 1
Это нормально, чтобы вводить службы в базу, но вы должны передавать их из класса User независимо. Вы не можете наследовать фактическое создание службы с базы, поэтому вам нужно передать ее на базу от пользователя. Это не ограничение TypeScript, а скорее особенность работы DI в целом.
Что-то вроде этого:
class User extends Base
constructor(service: AjaxService) {
super(service);
}
Если база создала службу для вас, вы не сможете повлиять на ее создание. Это отрицательно повлияло бы на многие преимущества DI в целом, поскольку вы потеряете контроль, делегируя управление зависимостями другому компоненту.
Я понимаю, что вы можете попытаться уменьшить дублирование кода, указав это в базе, но это противоречит принципу DI.
Ответ 2
Каждый класс в Angular 2, который вы хотите ввести, должен аннотировать. Если он не является компонентом, вы должны аннотировать его аннотацией @Injectable()
. Если вы добавляете класс, который уже вводит другой класс, вы должны создать для этого поставщика.
import {Injectable} from 'angular2/core';
import {Base} from './base';
@Injectable()
export class User extends Base {
}
Я создал Plunker для вас, надеюсь, что он решит вашу проблему:
http://plnkr.co/edit/p4o6w9GjWZWGfzA6cv41?p=preview
(посмотрите на вывод консоли)
PS. Пожалуйста, используйте Observable вместо Promises