Инъекция против глобального статического класса с Angular 2
Я создаю проект, в котором мне нужен класс "константы", чтобы содержать некоторые значения конфигурации. Вот выдержка этого класса:
export class Constants
{
static Configuration = class
{
static CookieName:string = 'etl_language';
};
...
static View = class
{
static Militaries:string = 'militaries';
static Mutants:string = 'mutants';
static Objects:string = 'objects';
static Scientists:string = 'scientists';
};
}
Когда я нахожусь в компоненте с Angular 2, я могу использовать этот класс, импортировав его:
import {Constants} from "../../misc/constants";
И тогда просто укажите его:
this.cookieName = Constants.Configuration.CookieName;
Он работает очень хорошо, но у меня возникает ощущение, что я должен использовать механизм впрыска зависимостей Angular 2, чтобы вставить ссылку на этот класс в конструкторе, но он кажется немного переборщиком. Тем не менее, у меня такое ощущение, что я нарушаю "способ Angular", поэтому не знаю, могу ли я придерживаться своего решения или мне нужно использовать DI.
Любые советы?
Ответы
Ответ 1
Вместо этого я могу предложить вместо этого изменить ваши классы Constants
, чтобы иметь свойства только для чтения и создать из них Providers[]
так
@Injectable()
public class ConfigurationConstants() {
private _cookieName:string = 'etl_language';
...
get cookieName():string {
return this._cookieName;
}
...
}
export var CONSTANTS_PROVIDERS:Provider[] = [
provide(ConfigurationConstants, {useClass: ConfigurationConstants}),
provide(ViewConstants, {useClass: ViewConstatns})
];
Затем вы можете загрузить эти поставщики в инжектор верхнего уровня для вашего приложения, сделав их доступными там, где они вам могут понадобиться.
import {CONSTANTS_PROVIDERS} from './constants';
bootstrap(App, [CONSTANTS_PROVIDERS])
.catch(err => console.error(err));
Здесь представлен фрагмент, демонстрирующий: http://plnkr.co/edit/RPjDxoIZ8wLY3DDIdhJF
Изменить 2: Теперь Plunker вернулся, и я обновил пример
Изменить: Plunkr уже мертв, поэтому я не могу его обновить, но в своем комментарии я имел в виду нечто подобное (я не тестировал это, но он должен работать):
public class SubConstants() {
private _someString:string = 'Some String';
...
get someString():string {
return this._someString;
}
...
}
@Injectable()
public class ConfigurationConstants() {
private _cookieName:string = 'etl_language';
private _subConstants:SubConstants = new SubConstants();
...
get cookieName():string {
return this._cookieName;
}
get subConstants():SubConstants {
return this._subConstants;
}
...
}
// ... this would allow you to then do:
confConstants.subConstants.someString
// assuming you injected ConfigurationConstants as confConstants
Опять же, это больше кода, чем ваше предложение о внутренних классах, поэтому оно, вероятно, зависит от того, что вы предпочитаете.
Ответ 2
DI является необязательным, но он хорош для случаев, когда вы хотите работать с экземпляром объекта. Импорт во многих случаях одобрен, но DI отделяет ваш код от экземпляра экземпляра. Это полезно, если вы выполняете автоматическое тестирование или хотите, чтобы ваш компонент был гибким и принимал любой объект с заданной подписью.
У меня есть дополнительная информация о DI здесь, если вы заинтересованы:
http://www.syntaxsuccess.com/viewarticle/dependency-injection-in-angular-2.0
Ответ 3
Мой совет, для чего это стоит. Никогда не используйте инъекцию зависимостей, если вы действительно не нуждаетесь в ней для решения проблемы.
Использование DI там, где это не требуется, или, что еще хуже, системное использование DI во всем приложении, чтобы удовлетворить некоторую чрезмерную структуру, приведет к непонятному коду. (Возможно, это относится к любому шаблону проектирования).
Angular иерархический DI кажется особенно вопиющим для меня. После того, как ваше приложение будет достаточно большим, чтобы решить, что такое конкретная зависимость, и что еще этот экземпляр разделяется, станет загадкой, пронизывающей всю вашу кодовую базу.