问题描述
我想在我的应用程序中创建身份验证装饰器.
呼叫应该简单如
@RequireAuthentication()
@HostListener('click', ['$event']) onClick(event: Event) {
....
}
我知道装饰器只能是功能,所以我打算在其他一些文件中使用
export function RequireAuthentication() {
if (!userService.isAuthenticated) {
navigationService.goToLogin();
return;
}
}
在这种情况下,我的问题是如何正确初始化userService和navigationService,因为这些服务包含用于查找用户是否已通过身份验证并显示登录屏幕的所有逻辑.
我已经尝试过:
- 使用带有构造函数的类进行服务初始化,但随后的嵌套方法不能用作装饰器
- 要使用Injectable类创建服务,我需要创建此类的实例,同样的问题.
- 使用ModuleWithProviders方法隐藏身份验证实现并仅公开装饰器,但不确定这样做是否正确.
任何提示都会有所帮助.可能是因为我没有经验丰富的角度开发人员,或者有另一种方法来解决此问题,所以我错过了一些基本知识.
提前谢谢!
如此答案中所述,对框架而言,惯用法是公开injector
类实例属性,因此可以在装饰器内部对其进行访问. injector
属性的存在也可以通过接口确保.
由于属性修饰器只运行一次并且可以访问类原型,但不能访问实例,因此有必要修补ngOnOnit
方法并使用this.injector.get()
检索修补方法内部的所有必要服务.
替代方法是将全局注入器暴露给某个对象,如此处.这不是惯用的解决方案,而是会导致某些限制和负面后果的骇客行为.几乎不建议将其用于生产中.
I want to create authentication decorator in my application.
Call should be simple as
@RequireAuthentication()
@HostListener('click', ['$event']) onClick(event: Event) {
....
}
As I know decorator can only be function, so in some other file I plan to have
export function RequireAuthentication() {
if (!userService.isAuthenticated) {
navigationService.goToLogin();
return;
}
}
Problem for me is how to properly initialize userService and navigationService in this case, since these services contains all logic for finding if user is authenticated and showing login screen.
I already tried:
- to use class with constructor for service initalization, but then nested method cannot be used as decorator
- to use Injectable class to create services, I need to create instance of this class, same problem.
- to use ModuleWithProviders approach to hide authentication implementation and only expose decorator, but not sure if that is right way to do this.
Any hints would be helpful. Could be that I miss something fundamental, since I'm not experienced angular developer or there is another way to approach this problem.
Thanks in advance!
As explained in this answer, the solution that is idiomatic to the framework is to expose injector
class instance property, so it could be accessed inside decorator. The existence of injector
property can be also secured with an interface.
Since property decorator runs once and has access to class prototype but not instance, it's necessary to patch ngOnOnit
method and retrieve all necessary services inside patched method with this.injector.get()
.
The alternative is to expose global injector to some object, as explained here. This is not idiomatic solution but a hack that will result in certain limitations and negative consequences. It can hardly be recommended for use in production.
这篇关于Angular 4 Custom装饰器-注入服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!