mercredi 28 octobre 2020

How to load a concrete implementation dynamically and parameterize the object creation?

Context

I am building a Chrome Extension that can receive commands and it shall be based on TypeScript. I want to extract concrete implementations of a class into it's own file that can be dynamically loaded.

Typescript dynamic loading command pattern

Example

In my chrome extension I receive the following JSON.

{
    "action": "get_tasking",
    "tasks": [
        {
            "command": "ConcreteContentCommand",
            "parameters": "{'param1': 'bla', 'param2': 'bla2'}",
            "timestamp": 1578706611.324671, //timestamp provided to help with ordering
            "id": "task uuid",
        }
    ]
}

First I'll load the appropriate file from IndexedDB that can be named ConcreteContentCommand.js containing the ConcreteContentCommand-Implementation. Now I want to create an instance of ConcreteContentCommand using the parameters param1, param2 that can then be used by my invoker.

class ContentReceiver {
  targetURL: string;
  payload: string;

  constructor(targetURL: string, payload: string) {
    this.targetURL = targetURL;
    this.payload = payload;
  }

  InjectRunnable() {
    // inject the payload into tab
    console.log(`Do something with ${this.payload}`);
  }
}

interface Command {
  execute(): void;
}

abstract class ContentCommand implements Command {
  receiver: ContentReceiver;

  protected constructor(url: string) {
    this.receiver = new ContentReceiver(url, this.runnable.toString());
  }

  abstract runnable(): void;

  execute() {
    this.receiver.InjectRunnable();
  }
}

abstract class BackgroundCommand implements Command {
  abstract runnable(): void;

  execute() {
    this.runnable();
  }
}

// This class shall be extracted, my extension will not know about this class
class ConcreteContentCommand extends ContentCommand {
  param1: string;
  param2: string;

  constructor(param1: string, param2: string) {
    super("https://staticurl");
    this.param1 = param1;
    this.param2 = param2;
  }

  runnable() {
    // Do Concrete Stuff here
  }
}

What options do I have to do this?

Aucun commentaire:

Enregistrer un commentaire