Inversifyjs: Error at resolve Service

Created on 28 Aug 2017  Â·  9Comments  Â·  Source: inversify/InversifyJS

I'm trying to resolve a dependency from a service class, the problem surge because a class has an "Http" constructor parameter (it uses this parameter for WebAPI requests.)

Expected Behavior


Resolve correctly the dependency and to use the represented object methods

Current Behavior


I have a console error that says :

Error: No matching bindings found for serviceIdentifier: Http

Possible Solution


Steps to Reproduce (for bugs)


Please see my Gist :)
https://gist.github.com/agomezgu/28f6de25624f035557bbee460c60003e

Context


I can't resolve any dependency from a concrete object that recibe a Http injectable parameter constructor. (Please see my Gist)

Your Environment

  • Version used: Angular 2
  • Environment name and version (e.g. Chrome 39, node.js 5.4):
  • Operating System and version (desktop or mobile):
  • Link to your project: https://gist.github.com/agomezgu/28f6de25624f035557bbee460c60003e

Stack trace


Error: Uncaught (in promise): Error: No matching bindings found for serviceIdentifier: Http↵Error: No matching bindings found for serviceIdentifier: Http↵ at _createSubRequests (http://localhost:4200/vendor.bundle.js:150398:19) [angular]↵ at Object.plan (http://localhost:4200/vendor.bundle.js:150417:5) [angular]↵ at http://localhost:4200/vendor.bundle.js:150113:37 [angular]↵ at Container._get (http://localhost:4200/vendor.bundle.js:150106:44) [angular]↵ at Container.get (http://localhost:4200/vendor.bundle.js:150065:21) [angular]↵ at new ReportComponent (http://localhost:4200/main.bundle.js:7735:95) [angular]↵ at createClass (http://localhost:4200/vendor.bundle.js:10996:26) [angular]↵ at createDirectiveInstance (http://localhost:4200/vendor.bundle.js:10832:37) [angular]↵ at createViewNodes (http://localhost:4200/vendor.bundle.js:12182:49) [angular]↵ at createRootView (http://localhost:4200/vendor.bundle.js:12087:5) [angular]↵ at Object.createProdRootView [as createRootView] (http://localhost:4200/vendor.bundle.js:12665:12) [angular]↵ at ComponentFactory_.create (http://localhost:4200/vendor.bundle.js:10023:46) [angular]↵ at ComponentFactoryBoundToModule.create (http://localhost:4200/vendor.bundle.js:3638:29) [angular]↵ at ComponentFactoryBoundToModule.create (http://localhost:4200/vendor.bundle.js:3638:29) [angular]↵ at resolvePromise (http://localhost:4200/polyfills.bundle.js:903:31) [angular]↵ at resolvePromise (http://localhost:4200/polyfills.bundle.js:874:17) [angular]↵ at http://localhost:4200/polyfills.bundle.js:951:17 [angular]↵ at Object.onInvokeTask (http://localhost:4200/vendor.bundle.js:4327:37) [angular]↵ at ZoneDelegate.webpackJsonp.1486.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.bundle.js:604:36) [angular]↵ at Zone.webpackJsonp.1486.Zone.runTask (http://localhost:4200/polyfills.bundle.js:404:47) [ => angular]↵ at drainMicroTaskQueue (http://localhost:4200/polyfills.bundle.js:784:35) []↵ at XMLHttpRequest.ZoneTask.invoke (http://localhost:4200/polyfills.bundle.js:662:25) []

Most helpful comment

What imports has 3. CONCRET OBJECT?

My first guess is that because of @injectable() inversify tries to inject Http into the constructor. But that is not added to myContainer.

An example project containing only the important code could be helpful :)

Sidenote:
Please don´t add +1 or I have the same problem. If you are interested in the topic click Subscribe. Then you get notifications. Thanks :)

All 9 comments

+1

+1

i have same problem.

What imports has 3. CONCRET OBJECT?

My first guess is that because of @injectable() inversify tries to inject Http into the constructor. But that is not added to myContainer.

An example project containing only the important code could be helpful :)

Sidenote:
Please don´t add +1 or I have the same problem. If you are interested in the topic click Subscribe. Then you get notifications. Thanks :)

Hi Lholznagel ,

Off course you are right ... i need inject the Http class , but i don't know what is the correct way to inject it , because this library is part of "@angular" Core.

Can you give me some advice?

Thank for all.

Hm without testing it I would say something like:
myContainer.bind<Http>(TYPES.Http).to(Http)

I always used the angular dependency injection so, I don´t know how to handle this the best way, sorry.

Would this work?

@agomezgu sorry for the bad news but Angular has been designed to work with its own IoC containers and it is quite difficult to replace it by other IoC containers like InversifyJS.

The Http source code can be found here. As we can see the constructor looks as follows:

@Injectable()
export class Http {
  constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {}
// ...

The @injectable() annotation in that source code comes from angular not from inversify. We need to add a second annotation @injectable() from inversify. The problems is that we can't use a decorator because we are not the authors of this class. There is a solution for this problem mentioned by @AltekkeE in the previous comment:

import { decorate, injectable } from "inversify";
import { Http } from "@angular/http";

decorate(injectable(), Http);

Then we can declare a binding:

container.bind<Http>(Http).toSelf();

And finally we can try to resolve:

const http = container.get<Http>(Http);

The problem is that the Http class needs two dependencies: ConnectionBackend and RequestOptions.

You can search for the source code of these two classes two see if they are public or private. If there are private there is nothing we can do (without ugly hacks). If they are public we can annotate them and declare bindings:

import { RequestOptions, ConnectionBackend } from "@angular/htttp";

decorate(injectable(), RequestOptions);
decorate(injectable(), ConnectionBackend);

container.bind<RequestOptions>(ConnectionBackend).toConstantValue(ConnectionBackend);
container.bind<RequestOptions>(RequestOptions).toSelf();

Note that ConnectionBackend uses toConstantValue because it is an abstract class (I know this because saw this in the source code).

Then we would have to repeat the operation for the dependencies of RequestOptions and ConnectionBackend and keep going. The worst part is that it is very likely that at some point you would find something private and you will not be able to continue.

In summary: I'm afraid that if your choice is angular, you will have to stick to the angular IoC container.

I actually asked about this to the Angular team when InversifyJS was in its early days: https://github.com/angular/angular/issues/6885

Hi Guys..

Finally I found a very usefull tool named InjectionToken , you can resolve dependencies using Interfaces, the principal advantage is, using InjectionToken you're using Angular Core and no external Libraries

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pmoleri picture pmoleri  Â·  5Comments

RastriginSergey picture RastriginSergey  Â·  3Comments

remojansen picture remojansen  Â·  4Comments

AlexanderKiriluyk picture AlexanderKiriluyk  Â·  4Comments

shevchenkobn picture shevchenkobn  Â·  3Comments