2016-08-19 3 views
0

"Webgl2RenderingContext"への参照を取得するためにAngular2依存性注入を使用しようとしていますが、createContext関数を呼び出すまで未定義です。いくつかの異なるサービスクラスに参照を挿入し、HTMLCanvasElementが利用可能になった後で値を設定する方法はありますか?Angular2依存性注入:最初に定義されていないプロパティへの参照を作成する

@Injectable() 
export class RenderContext { 
    get context() { return this.render_context; }; 

    constructor() { }; 

    createContext(canvas: HTMLCanvasElement) { 
     this.render_context = canvas.getContext("webgl2"); 
    }; 

    private render_context: WebGL2RenderingContext; 
} 

let get_context =() => { 
    return (render_context: RenderContext) => { 
     return render_context.context; 
    } 
} 

export const webgl2 = new OpaqueToken("webgl2"); 

export const webgl2_providers = [ 
    RenderContext, 
    { 
     provide: webgl2, 
     useFactory: get_context(), 
     deps: [RenderContext] 
    } 
]; 

答えて

1

それが1つのEMITコールを介して複数の観察者に送ることができますので、私は、RxJSから件名を、これは観測のために良いケースだと思います、そしておそらくあなたのケースインチ以下のコードでは、ReplaySubjectを使用しています。なぜなら、コンテキストが送信された後にサブジェクトにサブスクライブしても、最も再送される値を取得できるからです(つまり、コンテキストを作成する前に、コンテキストがすでに作成されているかどうかにかかわらず、コードを変更する必要はありません)。

@Injectable() 
export class RenderContext { 
    //import from 'rxjs/ReplaySubject' Provide Observable functionality to 
    //multiple observers, and will replay last-set value so those that subscribe 
    //after context is set still get the context. 
    private __contextSubject : ReplaySubject = new ReplaySubject(1); 

    private render_context: WebGL2RenderingContext; 

    constructor() { }; 

    //not using property getter now since returning Observable, not actual value 
    getContext() : Observable { 
     return this.__contextSubject; 
    }; 

    //send value to subscribers 
    private emitContext() { 
     this.__contextSubject.next(this.render_context); 
    } 

    //after storing context, also emit it to subscribers 
    createContext(canvas: HTMLCanvasElement) { 
     this.render_context = canvas.getContext("webgl2"); 
     this.emitContext(); 
    }; 

} 

次にあなたが(代わりに工場を経由で)直接てRenderContextを注入することにより、コンテキストになるだろう:私が見つけ

class OtherComponent { 
    constructor(renderContext: RenderContext) { 
     renderContext.getContext().subscribe(
      (context: WebGL2RenderingContext) => { 
       //do what you need to do with the context... 
      } 
     ) 
    } 
} 
0

一つの解決策は、MainCanvasコンポーネントのプロパティとしてReflectiveInjectorを作成していました「WebGL2RenderingContext」の初期化された値に単一のプロバイダを追加した後、コンテキストに依存する他のすべてのクラスを含む子インジェクタを作成します。

export class MainCanvas { 
    @ViewChild("canvas") canvas_ref: ElementRef; 

    private gl: WebGL2RenderingContext; 
    private context_injector: ReflectiveInjector; 
    private scene_renderer: SceneRenderer; 

    constructor(private render_context: RenderContext) {}; 

    ngAfterViewInit() { 
     this.render_context.createContext((<HTMLCanvasElement>this.canvas_ref.nativeElement)); 
     this.gl = this.render_context.context; 

     if (this.gl) { 

      let gl_provider = [{ provide: webgl2, useValue: this.gl }]; 

      this.context_injector = ReflectiveInjector.resolveAndCreate(gl_provider) 
       .resolveAndCreateChild([SceneRenderer, cube_providers, shader_providers]); 

      this.scene_renderer = this.context_injector.get(SceneRenderer); 
     } 
    } 
}; 

編集:それは子供のインジェクターを作ることなく動作します:

this.context_injector = ReflectiveInjector.resolveAndCreate([gl_provider, SceneRenderer, cube_provider, shader_providers]); 
関連する問題