Inversifyjs: Injecting an instance

Created on 17 May 2016  路  10Comments  路  Source: inversify/InversifyJS

Hi,

I have a question on how I can inject a class with constructor parameters that the interface that does not have:

export interface ApiRequestDecorator {
   decorateRequest(request : any);
}

then,

 export class BasicAuthDecorator implements ApiRequestDecorator {

    constructor(username : string, password : string) {
      ...
    }

    decorateRequest(request : any) : any {
      ...
    };
  }

I would then like to inject it into classes:

  constructor(
    @inject('ApiRequestDecorator') requestDecorator : ApiRequestDecorator
  ) {
    super();
    this.requestDecorator = requestDecorator;
  }

Would it be possible to do something like this:
kernel.bind<ApiRequestDecorator>("ApiRequestDecorator").to(new BasicAuthDecorator(username, password));

so that I can tell inversify how the instance must be created? I would like to avoid static classes.

question

Most helpful comment

I'm curious about this also. Is it possible to bind an already-instantiated instance into the container for some key? Is this what toConstantValue is for?

All 10 comments

Your ApiRequestDecorator entity is a class not an interface and then you are using:

BasicAuthDecorator implements ApiRequestDecorator

Instead of:

BasicAuthDecorator extends ApiRequestDecorator

Why do you need a class?

It's an interface, had to hand-write the code. Sorry!

Here are two examples that should help you:

Option A: Using a base class

class ApiRequestDecorator {
    public decorateRequest(request : any): void {

    };
}

@injectable()
class BasicAuthDecorator extends ApiRequestDecorator {

    private _username: string;
    private _password: string;

    public constructor(
        @inject("string") @named("username") username : string, 
        @inject("string") @named("password") password : string
    ) {
        super();
        this._username = username;
        this._password = password;
    }

    public decorateRequest(request : any) : void {
        super.decorateRequest(request);
    };
}

@injectable()
class SomeController {

    private _apiRequestDecorator: ApiRequestDecorator;

    public constructor(
        @inject("ApiRequestDecorator") apiRequestDecorator: ApiRequestDecorator
    ) {
        this._apiRequestDecorator = apiRequestDecorator;
    }

    public doSomething(request : any) {
        this._apiRequestDecorator.decorateRequest(request);
    }

}

let kernel = new Kernel();
kernel.bind<ApiRequestDecorator>("ApiRequestDecorator").to(BasicAuthDecorator);
kernel.bind<SomeController>("SomeController").to(SomeController);

// this is the important part
kernel.bind<string>("string").toConstantValue("your_username").whenTargetNamed("username");
kernel.bind<string>("string").toConstantValue("your_password").whenTargetNamed("password");

var controller = kernel.get<SomeController>("SomeController");
controller.doSomething(null);

Option B: Using an interface

interface ApiRequestDecorator {
    decorateRequest(request : any): void;
}

@injectable()
class BasicAuthDecorator implements ApiRequestDecorator {

    private _username: string;
    private _password: string;

    public constructorpublic constructor(
        @inject("string") @named("username") username : string, 
        @inject("string") @named("password") password : string
    ) {
        this._username = username;
        this._password = password;
    }

    public decorateRequest(request : any) : void {
        // DO SOMETHING
    };
}

@injectable()
class SomeController {

    private _apiRequestDecorator: ApiRequestDecorator;

    public constructor(
        @inject("ApiRequestDecorator") apiRequestDecorator: ApiRequestDecorator
    ) {
        this._apiRequestDecorator = apiRequestDecorator;
    }

    public doSomething(request : any) {
        this._apiRequestDecorator.decorateRequest(request);
    }

}

let kernel = new Kernel();
kernel.bind<ApiRequestDecorator>("ApiRequestDecorator").to(BasicAuthDecorator);
kernel.bind<SomeController>("SomeController").to(SomeController);

// this is the important part
kernel.bind<string>("string").toConstantValue("your_username").whenTargetNamed("username");
kernel.bind<string>("string").toConstantValue("your_password").whenTargetNamed("password");

var controller = kernel.get<SomeController>("SomeController");
controller.doSomething(null);

Please feel free to ask any questions we are here to help :wink:

@Davste93 I have updated my last comment I forgot the most important part :cry: To inject a value you need to use toConstantValue.

kernel.bind<string>("string").toConstantValue("your_username").whenTargetNamed("username");
kernel.bind<string>("string").toConstantValue("your_password").whenTargetNamed("password");

This is the critical part I was looking for. Thanks!

I would recommend you to take a look to all the features in the docs. I'm sorry I know the docs are really long :cry: but it is because there a lot of features :santa:

Would it not be possible to force inversify to inject an instance of BasicAuthDecorator which I created instead?

@remojansen Hi, I'm in trouble using your tip A. Option A: Using a base class
Because, it's not working, I must to have a @injectable label in my father class and I don't know why :(

export class Service {
  public log(error: Error) {
    winstonLog.error(error.stack);
  }
}

@injectable()
export class UserService extends Service {

  constructor(
      @inject(TYPES.UserRepository) private userRepository: UserRepository,
      @inject(TYPES.UserRoleService) private userRoleService: UserRoleService,
      @inject(TYPES.WarehouseAccountUserService) private warehouseAccountUserService: WarehouseAccountUserService,
      @inject(TYPES.TransactionWrapper) private transactionWrapper: TransactionWrapper,
      @inject(TYPES.AuthService) private authService: AuthService

  ) {
    super();
  }

error: uncaughtException: Missing required @injectable annotation in: Service

Hi @alfonsorios96 please refer to the page about inheritance in our wiki. Base classes require annotations as well.

I'm curious about this also. Is it possible to bind an already-instantiated instance into the container for some key? Is this what toConstantValue is for?

Was this page helpful?
0 / 5 - 0 ratings