Use service without constructor parameter

Hi there,

please read on, it’s really a simple question …

sooo … I have a class and it needs to use a service, but for some reason that class needs to have a constructor without parameters.

This is the aim, so it has to be very simple, like …

export class MyClass {
  constructor(){
    ...
  }
}

But I’ll have to use a Service in MyClass and to get the injected instance of that service, theres only one way I know to integrate the service, like …

import { MyService } from './somewhere';
export class MyClass {
  constructor(private myService: MyService){
    ...
  }
}

By the way: I allready registered MyService in app.module.ts (as a provider) …

import { MyService } from './somewhere';
@NgModule({
  ...
  providers: [
    MyService
  ]
})
export class AppModule {}

MyService has in its constructor many other parameters from services I don’t know. The above way constructor(private myService: MyService) has no problems to release me an instance at this.myService of MyService. So there’s no handling with the new keyword needed. Very nice …

Sooo … what do I have to do, to use MyService in MyClass? MyClass’s constructor must have not parameters. How to get that (singleton) instances of a service when usage of parameters are disallowed and when I can not and do not want use a line like myService = new MyService(...instances of classes I don't even know...);?

Thanks for any responses :slight_smile:

Why?

This sounds very strange.

My question is: Why do I need to use parameter values at myClass = new MyClass(bla bla) when MyClass uses services like constructor(private mySevice: MyService)? The private parameter … is private … and pulls its instance of MyService from somewhere else (internal injection service or so where MyService is allready instanciated and used like a sinlgeton I think) …

But when I use the new-keyword-way like myClass = new MyClass(bla bla), then I’ll need to set a value for mySevice, even if the parameter is private and its instance is pulled from somewhere else …

Do you understand what I mean? Sorry, my English … rusty …

Because you defined a contructor that needs a parameter. So you have to use it with a parameter. DI for classes whose new you normally don’t use, then the framework can take care of it. If you do use new you have to supply a class (as you wrote the code that requires this).

But my question was:
Why can’t your class have a parameter in the constructor as you said?

Generally speaking, you should never be directly instantiating anything with new in an Ionic app. This is absolutely, categorically true when, as is the case here, anything even gets a whiff of something managed by DI (as MyService is). So the problem isn’t MyClass's constructor, it’s the fact that you aren’t letting DI manage MyClass. You must do so.

Because MyClass is a model. It is used for JSON-parsing. Later I use Object.assign …

Like …

this.myModel = Object.create(MyModel.prototype);
Object.assign(this.myModel, JSON.parse(jsonString));

Later I need to use in loops someVar = new MyModel(). If MyModel uses a service in it’s construtor, I can use its instance inside of the model, no problem. But if I want to instanciate MyModel with new MyModel() I’ll need to use a value for the parameter.

Like …

export class SomeOtherClass {
  constructor(private myService: MyService){}
  ...
  for ...
    x = new MyModel(this.myService);
  ...
}

But what I don’t get is: Why does new MyModel needs that value? If SomeOtherClass is inherited I although need to set the constructor of the inheriting class with myService, all to have a value that I can set on the line with new MyModel(...)

This is f**** awkward. The main irritating is: Why do I need to set a value on a new-instanciation, when it’s value is pulled by the constructor of the class from somewhere else (it should be irrelevant what value I set on new MyModel(...) but it is not).

This is absolutely never going to work. Sorry, but you’re going to have to rethink the design. I recommend not getting cute like this trying to put intelligence in POD containers, but instead putting all the logic into service providers.

Trust me, it works. I use this way for years and it’s gold.

Details:
If you use this.myModel = JSON.parse(jsonString); you’ll have an instance of MyModel with fields but no methods or other members.

The following way instanciates MyModel with all its members on the regular way and appends the values to the fields of the actual instance of MyModel.

this.myModel = Object.create(MyModel.prototype);
Object.assign(this.myModel, JSON.parse(jsonString));

Two lines that saves your day :slight_smile:

Back to question:
Yeah … the Model has a private parameter in the constructor for an instance pulled from the DI. Why does it need to be set, when instanciated with new?

If I change the consturctor to something like constructor(private myService?: MyService) then this.myService is undefined every time (no automated instance-pull from the DI).

Isn’t there another way to get the service instance out of the DI?

You should investigate other frameworks. If you find a klugey way to do this in Angular, you’ll be fighting the framework for the entire life of your app.

You came here looking for advice. Not much any of us can do if you don’t want to listen to it.

But … the reality … it say’s it works … :frowning: … and now?

Please tone back or I will close this conversation. Your behaviour is not appropriate.

You got replies from 3 people telling you the same thing. Read them, understand them.

I did. So did @AaronSterling. Anything that touches any object managed by Angular’s DI must also be managed by Angular’s DI, so if you want the benefits of DI (and IMHO you should) you are going to have to give up on your homebrew lifecycle management.

Is there another way to get an service instance from the DI without using the private or public constructor parameter? Is there anywhere something like an injector service that holds a list of instances of other services?

(I actually don’t know.)

A step back: Why do you have to access a service/singleton in a model?

I actually had the same requirement as you - a data model needing a service (which was a common repo of utilities). I found various threads on making it work - this was one of them https://stackoverflow.com/questions/37482460/getting-instance-of-service-without-constructor-injection

I eventually reworked the code to ensure that the data model was pure data modeling (for lack of a better word) and did not need a service. I didn’t try these approaches, feel free to do so. I do think its a practical requirement (very imho) but found that Angular made it hard to do this and the solutions looked hacky.

2 Likes

Dear future reader who has somehow stumbled across this thread:

This is a perfect illustration of why I recommend using interfaces instead of classes for data encapsulation, especially when attempting to animate data that has come from an external source in the form of JSON. More discussion on the topic can be found here.

In principle, you can use Injector to create a service locator pattern, but the Angular docs say not to do this unless you really need to. My intuition is that if you’re going to code something that fancy to fight a framework, it would save a lot of time to find a framework that better fits your style.

2 Likes

@pliablepixels
THATS IT!!! THANK YOU :smile: It works as expected and the constructors of my models are clean and empty, nice and dandy :+1:

@Sujan12
I’m so sorry, if you missunderstood me. I’m not fighting any framework, I try to understand, what the DI does in the background and how to access it without the help of constructor parameters, please keep this in mind.

So … Shouldn’t I use methods in models? Is it not normal to have methods in models? Like loading stuff from the storage or getting an array of sorted information? Perhaps I plan my models false … What’s your advice? Should I move all model-methods to the service? Like @rapropos said: Should I use interfaces instead and get rid of that fancy other members as the fields in my model classes? Thanks for your hint with the service locator pattern :slight_smile:

@rapropos
What about your JSON-parsed interfaces when they can have methods and could be real class instances? Your interfaces could just hold some fields when classes can give you much more options … like methods … you know?

Would you mind letting me know which method you finally used ? (there were multiple approaches) and maybe a code snippet? I keep a secret pouch of ugly ‘never do it this way’ code fragments that actually make my life easier but would be taboo if brought up.