Where to define the constructor's arguments, if they are not supposed to be injected? For example, how would i provide the constructor argument customAppSettingsHome?
@injectable()
export class EnvironmentService implements IEnvironmentService {
get args(): ParsedArgs { return this._args; }
get execPath(): string { return this._execPath; }
constructor(
@unmanaged private _args: ParsedArgs,
@unmanaged private _execPath: string
) { }
}
@injectable()
export class ConfigurationService<T>
extends Disposable implements IConfigurationService, IDisposable {
constructor(
@inject('environmentService') environmentService: IEnvironmentService
) {
super();
}
....
}
@injectable()
export class SettingsTestEnvironmentService extends EnvironmentService {
constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome) {
super(args, _execPath);
}
get appSettingsPath(): string { return this.customAppSettingsHome; }
}
When running the test scenario
let container = new Container();
container.bind<IEnvironmentService>("IEnvironmentService")
.to(SettingsTestEnvironmentService);
const customAppSettingsHome = {
editor: {
fontFamily: 'foo',
fontSize: 1
},
terminal: {
integrated: {
fontFamily: 'bar',
fontSize: 2
}
}
});
I'm not 100% sure about your problem but I think what you are trying is:
@injectable()
export class ConfigurationService<T>
extends Disposable implements IConfigurationService, IDisposable {
constructor(
@inject('environmentService') EnvironmentService: IEnvironmentService
) {
// Create EnvironmentService by hand?
let environmentService = new EnvironmentService(/*...*/, "", { /*...*/ });
super();
}
....
}
If that is the case, then all you need is toConstructor:
container.bind<IEnvironmentService>("IEnvironmentService")
.toConstructor(SettingsTestEnvironmentService);
Please refer to the "Injecting a class constructor" wiki page for more details.
Does this solve your problem? Can the issue be closed?
I'm trying to find a way to pass the constructor argument. For example, if we instantiate the class outside inversify we do the following way. But with inversify to instantiate, how to achieve this?
const env = new SettignsTestEnvironmentService(args, path, customAppSettingsHome);
@remojansen
If I'm not wrong, I can do the following, right?
container.bind<IEnvironmentService>("IEnvironmentService")
.toValue(new SettignsTestEnvironmentService(args, path, customAppSettingsHome));
Nearly there:
const config = new SettignsTestEnvironmentService(args, path, customAppSettingsHome);
container.bind<IEnvironmentService>("IEnvironmentService").toConstantValue(config);
Thanks for clarifying. What if we have mixed one like the following. How to pass Platform argument into the constructor.
@injectable()
export class ConfigurationService<T>
extends Disposable implements IConfigurationService, IDisposable {
constructor(
private _platform: Platform,
@inject('environmentService') environmentService: IEnvironmentService
) {
super();
}
....
}
In that case you need a setter:
@injectable()
export class ConfigurationService<T>
extends Disposable implements IConfigurationService, IDisposable {
private _platform: Platform,
constructor(
@inject('environmentService') environmentService: IEnvironmentService
) {
super();
}
public setPlatform(platform: Platform) {
this._platform: Platform;
}
....
}
Or a factory:
class ConfigurationService<T>
extends Disposable implements IConfigurationService, IDisposable {
constructor(
private _platform: Platform,
environmentService: IEnvironmentService
) {
super();
}
....
}
container.bind<(platform: Platform) => ConfigurationService>("ConfigurationService").toFactory<ConfigurationService>((context: interfaces.Context) => {
return (platform: Platform) => {
let environmentService = context.container.get<Katana>("Katana");
return new ConfigurationService(platform, environmentService);
};
});
let configurationServiceFactory = container.get<(platform: Platform) => ConfigurationService>("ConfigurationService");
let configurationService = configurationServiceFactory(/* ... platform ... */);
Hi @veeramarni can this issue be closed?
@remojansen
That worked very well, I think using a Factory is very clean. Thanks for this amazing package.
@remojansen
I think we should reduce the boilerplate code especially if we have Hierarchical DI system and we need to expose child's Interfaces and Symbols by parent classes to instantiate the child classes.
Can we accomplish the same thing similar to createInstance in
https://github.com/veeramarni/vscode/blob/master/src/vs/platform/instantiation/common/instantiationService.ts ?
I have checked this note, but can we inject something like serviceInstance to the child classes instead of creating a new container to reduce the boilerplate code as above.
Please let me know your feedback.
I solved this by removing the parameter from the constructor and passing it directly to the method where I'm using it:
@injectable()
export class ConfigurationService<T>
extends Disposable implements IConfigurationService, IDisposable {
constructor(
@inject('environmentService') environmentService: IEnvironmentService
) {
super();
}
doSomethingWithPlatform(platform: Patform) {...}
}
Another solution is also removing the parameter from the constructor and using a setter for it.
Most helpful comment
In that case you need a setter:
Or a factory: