如何使用 Inject 获取一次服务实例
How to get once instance of service with Inject
如何使用 Injector 获得相同的一次单例服务实例:
我在 bootstrap 应用程序上定义了此服务的提供者(对于所有应用程序的一个实例)
示例:
Bootstrap申请
//Init application
bootstrap(AppComponent, [ROUTER_PROVIDERS, HTTP_PROVIDERS, SessionService]);
会话服务
单例 - 这只是示例,但实际上可以是会话或 acl 服务
@Injectable()
export class SessionService {
constructor() {
console.warn("INSTANCE OF SESSION SERVICE-a");
}
public getInstance(instanceName: string){
console.warn("Injected service come from component name: " + instanceName);
}
}
SecuredHomeComponent
当我在构造函数上注入服务时,只有一次服务实例(好)
@Component()
@CanActivate(AccessService.checkSession)
export class SecuredHomeComponent {
public constructor(private testSessionService: SessionService) {
this.testSessionService.getInstance('Component1:1'); //Test 1 - get the same instance when service is inject into contructor
}
}
MyStaticService
我这样尝试,注入服务但总是得到新的服务实例
但是我需要使用 "Injector.resolveAndCreate" 直接注入例如静态方法,然后 NG2 创建新的服务实例 (bad)
@Injectable()
export class MyStaticService {
public static getDataFromService() {
//That two ways is bad, bcs create new instance of my test SessionService
//Test4
let providers = Injector.resolve([ SessionService ]);
let injectorFirst = Injector.fromResolvedProviders(providers);
let testServFirst = injectorFirst.get(SessionService);
testServFirst.getInstance('StaticService1:1');
//Test 5
let injectorSecond = Injector.resolveAndCreate([SessionService]);
let testServSecond = injectorSecond.get(SessionService);
testServSecond.getInstance('StaticService1:2');
}
}
静态服务
对于真实示例,我需要使用静态方法的静态 class
如果我很好地理解文档,当想要覆盖注释的方法时 canActivate 必须提供带有静态方法的服务
行:我的"SecuredHomeComponent"
中的@CanActivate(AccessService.checkSession)
//Static Service - ACCESS
@Injectable()
export class AccessService {
public static checkAccess = (next: ComponentInstruction, prev: ComponentInstruction): boolean => {
return AccessService.checkSession() && AccessService.checkAcl(res, priv);
}
public static checkSession(): boolean {
let injectedSessionServices: SessionService; //How to inject the same instance of my SessionService?
return injectedSessionServices.getDataFromService(); //for real service he get back checkSession from sessionService
}
public static checkAcl(aclResource: AclResources, aclPrivilege: AclPrivileges): boolean {
let injectedAclServices: SessionService; //How to inject the same instance of my SessionService?
return injectedAclServices.checkAcl(aclResource, aclPrivilege);
}
}
Angulars DI 为每个提供者保留一个实例。如果从同一个提供者请求一个实例,则每次都返回同一个实例。
你可以做的是,提供一个工厂并调用工厂来获取新的实例。
bootstrap(AppComponent, [provide(CommonTestService, {useFactory: () => {
return () => {
new CommonTestService();
}
})]);
如果服务本身有依赖项(构造函数参数),那么您也需要提供它们
bootstrap(AppComponent, [MyServiceDependency, provide(CommonTestService, {useFactory: () => {
return () => {
new CommonTestService(dep);
},
deps: [MyServiceDependency]
})]);
那你就可以像这样使用了
@Component()
export class HomeComponent {
public constructor(@Inject(CommonTestService) private testService:any) {
let s1 = testService(); // new instance
let s2 = testService(); // new instance
..
}
}
我找到了使用一个全局服务实例的解决方案 injector 实现了标准单例 class getInstance() 到 bootstrap申请。然后可以在所有级别的应用程序上获得注入服务的简单实例。如果有时间有人找到不同的解决方案,或者 NG2 解决了这个不同的问题,请告诉我。
非常简单的示例代码:
Bootstrap 应用
//Init application
bootstrap(AppComponent, [ROUTER_PROVIDERS, MY_PROVIDERS, HTTP_PROVIDERS])
.then((appRef) => MainInjectorService.getInstance().setInjector(appRef.injector));
我的帮手主喷油器
import { Injector, Injectable } from 'angular2/src/core/di';
@Injectable()
export class MainInjectorService
{
static instance:MainInjectorService;
static isCreating:Boolean = false;
private _injector: Injector;
constructor() {
if (!MainInjectorService.isCreating) {
throw new Error("You can't call new in Singleton instances!");
}
}
public static getInstance() {
if (MainInjectorService.instance == null) {
MainInjectorService.isCreating = true;
MainInjectorService.instance = new MainInjectorService();
MainInjectorService.isCreating = false;
}
return MainInjectorService.instance;
}
public setInjector(injector: Injector) {
this._injector = injector;
}
public getInjector(): Injector {
return this._injector;
}
}
我的静态 class
// Access - static service
@Injectable()
export class StaticAccessService {
// Get service instance from global provides service
private static _getService<T>(serviceName: any) {
let injector: Injector = MainInjectorService.getInstance().getInjector();
return injector.get(serviceName);
}
//Check access to session and acl
public static checkAccess = (next: ComponentInstruction, prev: ComponentInstruction): boolean => {
return StaticAccessService.checkSession() && StaticAccessService.checkAcl(next.routeData.data['res'], next.routeData.data['priv']);
}
// Check session access
public static checkSession(): boolean {
return StaticAccessService._getService(MySessionService).checkSession();
}
// Check session access
public static checkAccess(res, priv): boolean {
return StaticAccessService._getService(MyAclService).checkAccess(res, priv);
}
}
以及如何在组件中使用
@Component()
@CanActivate(StaticAccessService.checkAccess)
export class SecuredComponent {
}
如何使用 Injector 获得相同的一次单例服务实例:
我在 bootstrap 应用程序上定义了此服务的提供者(对于所有应用程序的一个实例)
示例:
Bootstrap申请
//Init application
bootstrap(AppComponent, [ROUTER_PROVIDERS, HTTP_PROVIDERS, SessionService]);
会话服务
单例 - 这只是示例,但实际上可以是会话或 acl 服务
@Injectable()
export class SessionService {
constructor() {
console.warn("INSTANCE OF SESSION SERVICE-a");
}
public getInstance(instanceName: string){
console.warn("Injected service come from component name: " + instanceName);
}
}
SecuredHomeComponent
当我在构造函数上注入服务时,只有一次服务实例(好)
@Component()
@CanActivate(AccessService.checkSession)
export class SecuredHomeComponent {
public constructor(private testSessionService: SessionService) {
this.testSessionService.getInstance('Component1:1'); //Test 1 - get the same instance when service is inject into contructor
}
}
MyStaticService
我这样尝试,注入服务但总是得到新的服务实例 但是我需要使用 "Injector.resolveAndCreate" 直接注入例如静态方法,然后 NG2 创建新的服务实例 (bad)
@Injectable()
export class MyStaticService {
public static getDataFromService() {
//That two ways is bad, bcs create new instance of my test SessionService
//Test4
let providers = Injector.resolve([ SessionService ]);
let injectorFirst = Injector.fromResolvedProviders(providers);
let testServFirst = injectorFirst.get(SessionService);
testServFirst.getInstance('StaticService1:1');
//Test 5
let injectorSecond = Injector.resolveAndCreate([SessionService]);
let testServSecond = injectorSecond.get(SessionService);
testServSecond.getInstance('StaticService1:2');
}
}
静态服务
对于真实示例,我需要使用静态方法的静态 class 如果我很好地理解文档,当想要覆盖注释的方法时 canActivate 必须提供带有静态方法的服务
行:我的"SecuredHomeComponent"
中的@CanActivate(AccessService.checkSession)//Static Service - ACCESS
@Injectable()
export class AccessService {
public static checkAccess = (next: ComponentInstruction, prev: ComponentInstruction): boolean => {
return AccessService.checkSession() && AccessService.checkAcl(res, priv);
}
public static checkSession(): boolean {
let injectedSessionServices: SessionService; //How to inject the same instance of my SessionService?
return injectedSessionServices.getDataFromService(); //for real service he get back checkSession from sessionService
}
public static checkAcl(aclResource: AclResources, aclPrivilege: AclPrivileges): boolean {
let injectedAclServices: SessionService; //How to inject the same instance of my SessionService?
return injectedAclServices.checkAcl(aclResource, aclPrivilege);
}
}
Angulars DI 为每个提供者保留一个实例。如果从同一个提供者请求一个实例,则每次都返回同一个实例。
你可以做的是,提供一个工厂并调用工厂来获取新的实例。
bootstrap(AppComponent, [provide(CommonTestService, {useFactory: () => {
return () => {
new CommonTestService();
}
})]);
如果服务本身有依赖项(构造函数参数),那么您也需要提供它们
bootstrap(AppComponent, [MyServiceDependency, provide(CommonTestService, {useFactory: () => {
return () => {
new CommonTestService(dep);
},
deps: [MyServiceDependency]
})]);
那你就可以像这样使用了
@Component()
export class HomeComponent {
public constructor(@Inject(CommonTestService) private testService:any) {
let s1 = testService(); // new instance
let s2 = testService(); // new instance
..
}
}
我找到了使用一个全局服务实例的解决方案 injector 实现了标准单例 class getInstance() 到 bootstrap申请。然后可以在所有级别的应用程序上获得注入服务的简单实例。如果有时间有人找到不同的解决方案,或者 NG2 解决了这个不同的问题,请告诉我。
非常简单的示例代码:
Bootstrap 应用
//Init application
bootstrap(AppComponent, [ROUTER_PROVIDERS, MY_PROVIDERS, HTTP_PROVIDERS])
.then((appRef) => MainInjectorService.getInstance().setInjector(appRef.injector));
我的帮手主喷油器
import { Injector, Injectable } from 'angular2/src/core/di';
@Injectable()
export class MainInjectorService
{
static instance:MainInjectorService;
static isCreating:Boolean = false;
private _injector: Injector;
constructor() {
if (!MainInjectorService.isCreating) {
throw new Error("You can't call new in Singleton instances!");
}
}
public static getInstance() {
if (MainInjectorService.instance == null) {
MainInjectorService.isCreating = true;
MainInjectorService.instance = new MainInjectorService();
MainInjectorService.isCreating = false;
}
return MainInjectorService.instance;
}
public setInjector(injector: Injector) {
this._injector = injector;
}
public getInjector(): Injector {
return this._injector;
}
}
我的静态 class
// Access - static service
@Injectable()
export class StaticAccessService {
// Get service instance from global provides service
private static _getService<T>(serviceName: any) {
let injector: Injector = MainInjectorService.getInstance().getInjector();
return injector.get(serviceName);
}
//Check access to session and acl
public static checkAccess = (next: ComponentInstruction, prev: ComponentInstruction): boolean => {
return StaticAccessService.checkSession() && StaticAccessService.checkAcl(next.routeData.data['res'], next.routeData.data['priv']);
}
// Check session access
public static checkSession(): boolean {
return StaticAccessService._getService(MySessionService).checkSession();
}
// Check session access
public static checkAccess(res, priv): boolean {
return StaticAccessService._getService(MyAclService).checkAccess(res, priv);
}
}
以及如何在组件中使用
@Component()
@CanActivate(StaticAccessService.checkAccess)
export class SecuredComponent {
}