[英]Angular2 dependency injection: creating a reference to a property that is initially undefined
我正在尝试使用Angular2依赖项注入来获取对“ Webgl2RenderingContext”的引用,该引用在我调用createContext函数之前是不确定的。 有没有办法将引用注入到几个不同的服务类中,然后在HTMLCanvasElement可用之后设置值?
@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]
}
];
我认为这对于Observables来说是一个很好的案例,对您而言,这可能是RxJS的Subject,因为它允许通过一个generate调用发送给多个观察者。 在下面的代码中,我使用了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...
}
)
}
}
我发现的一个解决方案是创建一个ReflectiveInjector作为MainCanvas组件的属性,在创建“ 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]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.