如何使用Inject

时间:2016-03-25 15:25:53

标签: angular angular2-services

如何使用Injector获得相同的单例服务实例:

我在bootstrap应用程序上定义了这个服务的提供者(对于所有应用程序中的一个实例)

示例:

引导程序

//Init application
bootstrap(AppComponent, [ROUTER_PROVIDERS, HTTP_PROVIDERS, SessionService]);

SessionService

Singleton - 这只是示例,但实际上可以是session或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创建新的服务实例(差)

@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');
    }
}

静态服务

对于实例,我需要静态类和静态方法 如果我很好理解doc,当想要覆盖注释的方法 canActivate 必须提供静态方法的服务

行:@CanActivate(AccessService.checkSession)在我的" SecuredHomeComponent"

//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);
    }
}

2 个答案:

答案 0 :(得分:2)

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
    ..
  }
}

答案 1 :(得分:0)

我找到了一个解决方案,使用一个全局服务实例 injector 实现了带有 getInstance()的标准单例类到bootstrap应用程序中。之后,可以在所有级别的应用程序上获得注入服务的简单实例。如果有人找到不同的解决方案,或者NG2解决了这个问题,请告诉我。

非常简单示例的示例代码:

Bootstrap app

//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;
    }
}

我的STATIC课程

// 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 {
}