Possible to register static only protocols? - swinject

Unfortunately, some libraries only have static methods to them. Is it possible to make Swinject register a type to return a type instead of an instance of a type? Makes it hard to stub out static only libraries for testing.

In the current state of the Swinject this is unfortunately not possible. One of the ways you could work around this would be creating a custom type provider:
protocol LibraryProtocol {}
class Library: LibraryProtocol {}
class LibraryProvider {
let library: LibraryProtocol.Type
init(_ library: LibraryProtocol.Type) { self.library = library }
}
container.register(LibraryProvider.self) { _ in LibraryProvider(Library.self) }

Related

What is a Rust equivalent to C++'s virtual overwriting to prevent code rewriting?

In C++, I've written this code:
class MessageHandler {
virtual MediaPlayer::Ptr handle_message(...);
virtual RtspServer::Ptr decideRtspServer(...);
virtual RtspClient::Ptr decideRtspClient(...);
virtual Decoder::Ptr decideDecoder(...);
virtual Renderer::Ptr decideRenderer(...);
};
This class handles a message that informs which RtspServer, RtspClient, Decoder, Renderer to use, and returns a MediaPlayer. I want to write MessageHandlers for lots of devices: Android, Windows, Linux, etc, so I can override each decision. For example, I can override decideRenderer to decide an specific renderer that is only available in Linux, but the rest should not be overridden as it's the same in all devices.
I'm looking to do the same in Rust: have default decisions but the ability to "override" one if needed, when implementing a MessageHandler for an specific device.
How can I achieve something similar in Rust? I don't care if it looks like OOP or not, I just want to prevent rewriting the same code.
What speaks against trait objects? Something along the lines of this:
trait MessageHandler {
handle_message(...) -> Box<MediaPlayer> {
Box::new(DefaultMediaPlayer{})
}
decideRtspServer(...) -> Box<RtspServer> {
Box::ne(DefaultRtspServer{})
}
// and others
};
struct LinuxMessageHandler {...}
impl MessageHandler for LinuxMessageHandler {
handle_message(...) -> Box<MediaPlayer> {
Box::new(LinuxSpecificMediaPlayer{})
}
// do not implement any other method: instead, automatically "inherit" them from MessageHandler
}
Then, these "trait objects" are passed around as e.g. Box<dyn MessageHandler>.

How do I use an IOC container with typescript generics in node?

I am attempting to use container-ioc, but am happy to use any package supplying IoC. I cannot find any examples that use typescript generics. Basically, I want:
interface A<T> {
foo();
}
class A<T> {
foo() {
}
}
interface B<T> {
bar: A<T>;
}
class B<T> {
bar: A<T>;
constructor(param: A<T>) {
this.bar = param;
}
}
where I can set up an IoC container to inject A into B. I am using typescript in a node app. I have syntax that seems to parse at least, but cannot craft the container resolve() as I don't know how to pass the generic parameter. Not to mention, I'm not sure whether this is actually supported.
So, I have a workaround that works for my situation. Firstly, I set a symbol for the generic type with const MyFoo = Symbol("Foo<My>"). Then, I use a factory constructor when registering the type:
container.register([
{ token: MyBar, useFactory: () => new Bar<My>() },
token: MyFoo, useFactory: () => new Foo<My>( container.resolve(MyBar) )}]);
Finally, I do not #inject the parameter on the constructor. This method means that I need to know what generic types I will be using beforehand. In my case, I do: my generic types implement an entity repository and related classes, and my entities are the generic parameters. I'd prefer to not have yet another place to maintain when setting up new entities, so I am leaving this answer unaccepted in case someone has a better solution.

inversify: how to handle binding to a generic interface/class

I am using inversify for an mean stack application developed with typescript. Following the instructions here at this url: https://www.npmjs.com/package/inversify, I created the inversify.config.ts file and added the code relevant to my needs. I am receiving the following error for one of my binding:
"Error:(39, 71) TS2349:Cannot invoke an expression whose type lacks a call signature. Type 'typeof ExampleRepository' has no compatible call signatures.".
inversify.config.ts:
myContainer.bind<IExampleRepository<IGroup>>(TYPES.IExampleRepository).to(ExampleRepository<IGroup>).whenTargetNamed("exampleRepository");
types.ts:
IExampleRepository: Symbol("ExampleRepository")
How would the inversify.config.ts entry have to change to accomodate this need? What am I doing wrong here? Can inversify handle this scenario?
I think that if your interface is generic IExampleRepository<T> then your ExampleRepository doesn't need the <IGroup> generic on it.
import { Container, injectable } from "inversify";
const TYPES = {
IExampleRepository: Symbol("IExampleRepository"),
};
class IGroup {
}
interface IExampleRepository<T> {
group: T;
}
#injectable()
class ExampleRepository implements IExampleRepository<IGroup> {
group: IGroup
}
const myContainer = new Container();
myContainer.bind<IExampleRepository<IGroup>>(TYPES.IExampleRepository).to(ExampleRepository).whenTargetNamed("exampleRepository");
`
Please provide more example code for IExampleRepository and Examplerepository. That might help get a better answer.

Typescript IOC in case of node

I am wondering how would you use typescript IOC specifically node app.
In case of external module-based architecture there is no any classes in the app. Just pure modules because my app heavily depends on node_modules.
How would I integrate IOC solution in such case? Any thoughts?
Here is my specific case I want to use IOC for:
I have mongoose model:
interface IStuffModel extends IStuff, mongoose.Document { }
var Stuff= mongoose.model<IStuffModel>('Stuff', Schemas.stuffSchema);
export = Stuff;
And related fake class:
export class Stuff implements IStuff {
//do stuff
}
How would I integrate IOC solution in such case
Here is a very popular library that I recommend : https://github.com/inversify/InversifyJS
External modules
Using external modules doesn't change the code at all. Instead of
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", FooBar));
Production
You just have
import {ProdFooBar} from "./prodFooBar";
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", ProdFooBar));
Test
import {MockFooBar} from "./mockFooBar";
kernel.bind(new TypeBinding<FooBarInterface>("FooBarInterface", MockFooBar));
As Basarat indicated in his answer, I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings.
You need to follow 3 basic steps to use it:
1. Add annotations
The annotation API is based on Angular 2.0:
import { injectable, inject } from "inversify";
#injectable()
class Katana implements IKatana {
public hit() {
return "cut!";
}
}
#injectable()
class Shuriken implements IShuriken {
public throw() {
return "hit!";
}
}
#injectable()
class Ninja implements INinja {
private _katana: IKatana;
private _shuriken: IShuriken;
public constructor(
#inject("IKatana") katana: IKatana,
#inject("IShuriken") shuriken: IShuriken
) {
this._katana = katana;
this._shuriken = shuriken;
}
public fight() { return this._katana.hit(); };
public sneak() { return this._shuriken.throw(); };
}
2. Declare bindings
The binding API is based on Ninject:
import { Kernel } from "inversify";
import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";
var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
export default kernel;
3. Resolve dependencies
The resolution API is based on Ninject:
import kernel = from "./inversify.config";
var ninja = kernel.get<INinja>("INinja");
expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
The latest release (2.0.0) supports many use cases:
Kernel modules
Kernel middleware
Use classes, string literals or Symbols as dependency identifiers
Injection of constant values
Injection of class constructors
Injection of factories
Auto factory
Injection of providers (async factory)
Activation handlers (used to inject proxies)
Multi injections
Tagged bindings
Custom tag decorators
Named bindings
Contextual bindings
Friendly exceptions (e.g. Circular dependencies)
You can learn more about it at https://github.com/inversify/InversifyJS
In the particular context of Node.js there is a hapi.js example that uses InversifyJS.

Dependency injection php

I have built a simple dependency injection container that I pass around my classes that need it, everything works and all is good.
My question is that say I have 2 classes such as
class A {
public function __construct() {
}
}
class B {
public function __construct(A $a) {
}
}
Should I enforce the typehinting in the class itself or in the injection container such as;
$di->set('A', function() {
return new A();
});
$di->set('B', function(A $a) {
return new B($a);
});
Should I do both or either/or.
For answers why is it better to use one over the other etc?
Thanks.
I would use the first case, enforce the type hinting in the class itself.
This will make it clear for readers of the code what are the actual dependencies of the class.
If you decide to change the DI container (or hypothetically remove it) or reuse the classes in other project, it is good to have the type hinting in the class itself.
The DI container is there simply to help you manage dependencies.

Resources