繁体   English   中英

Angular2依赖项注入:创建对最初未定义属性的引用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM