Gives an error:
Target [MyVendor\ProductList\ProductServiceInterface] is not instantiable.
ProductServiceInterface
namespace MyVendor\ProductList;
interface ProductServiceInterface
{
public function productList();
public function getProductSpeed();
}
ProductColorService
namespace MyVendor\ProductList\Service;
abstract class ProductColorService implements \MyVendor\ProductList\ProductServiceInterface
{
public function productList()
{
$color = "black";
return $color;
}
}
** ProductSpeedService **
namespace MyVendor\ProductList\Service;
abstract class ProductSpeedService implements \MyVendor\ProductList\ProductServiceInterface {
public function getProductSpeed() {
$speed = 200;
return $speed;
}
}
Provider :
namespace MyVendor\ProductList;
use Illuminate\Support\ServiceProvider;
use MyVendor\ProductList\ProductServiceInterface;
use MyVendor\ProductList\Service\ProductColorService;
class ProductColorServiceProvider extends ServiceProvider
{
public function boot()
{
$this->loadRoutesFrom(__DIR__ . '/routes/color.php');
}
public function register()
{
$this->app->bind('MyVendor\ProductList\ProductServiceInterface','MyVendor\ProductList\Service\ProductColorService');
$this->app->bind('MyVendor\ProductList\ProductServiceInterface','MyVendor\ProductList\Service\ProductSpeedService');
}
}
Whats wrong in this code? Actually I need to override some functions in interface using service. ie each service should override one method.
namespace MyVendor\ProductList\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use MyVendor\ProductList\Models\Product;
use MyVendor\ProductList\ProductServiceInterface;
class ProductListController extends Controller
{
public function index(ProductServiceInterface $product_service)
{
$color = $product_service->productList();
$speed = $product_service->getProductSpeed();
dd($color," = ",$speed);
$product = Product::get();
return view('ProductList::product',compact('product'));
}
}
here productList() in one service and productSpeed() from another service
You can't instantiate abstract classes. The whole point of them is there can never be an instance of them, so if you bind your interface to your abstract class with a method, it simply can never be abstract. Abstract is for classes in inheritance structures you do not want to have the users to create new ones.
So there is no reason for the abstract, abstract is for something like this.
abstract class Vehicle {
protected $wheels;
public function getWheels() {
return $this->wheels;
}
}
class Car extends Vehicle {
protected $wheels = 4;
}
class Bike extends Vehicle {
protected $wheels = 2;
}
You can not make a vehicle as it is not a concrete implementation, as it is a parent class to help with methods shared across two classes. So short version, just remove the abstract keyword. If you don't know why you add it, it is not needed.
Lets say I have Bundle A, and it has an Interface HelloWorld and function helloWorld()
Now, in another bundle B, I'm implementing as follows
#Service(HelloWorld.class)
#Component(immediate = true)
public class Test1Impl implements HelloWorld
{
public String helloWorld()
{
return "I'm from Bundle B";
}
}
I've another bundle C, I'm doing
#Service(HelloWorld.class)
#Component(immediate = true)
public class Test2Impl implements HelloWorld
{
public String helloWorld()
{
return "I'm from Bundle C";
}
}
Now if I need to get implementation of Bundle C only then what should I do?
For example in general I do as below but it does not work in this case.
Helloworld obj = sling.getService(HelloWorld.class);
obj.helloWorld();
You can use properties and filter to choose which implementation you want to get.
For example, you can put a property on the implementation in the bundle C :
#Service(HelloWorld.class)
#Component(immediate = true)
#Property(name = "bundle", value = "bundle-c")
public class Test2Impl implements HelloWorld { .. }
then use a filter to get this implementation. you'll get an array of services matching the filter.
HelloWorld[] services = sling.getServices(HelloWorld.class, "(bundle=bundle-c)")
By default, DS put a property with the name of the component. This property is "component.id", and the name of the component is by default the full classname of the implementation. So you can use too:
HelloWorld[] services = sling.getServices(HelloWorld.class, "(component.id=package.Test2Impl)")
I have a number of classes, POJO style, that shares a single functionality, say readCSV method. So I want to use a single parent (or maybe abstract, not sure if it should be) class that these POJOs can extend. Here's a pseudo-code:
(abstract) class CSVUtil {
private String[] fileHeader = null;
protected void setFileHeader(fileHeader) {
this.fileHeader = fileHeader;
}
protected List<WhateverChildClass> readCSV(String fileName) {
// read CSV using Apache Commons CSV
// and return a List of child type
List<WhateverChildClass> list = null;
// some declarations
try {
list = new ArrayList<WhateverChildClass>();
csvParser = new CSVParser(fileReader, csvFormat);
List csvRecords = csvParser.getRecords();
for (...) {
CSVRecord record = (CSVRecord) csvRecords.get(i);
WhateverChildClass childClass = new WhateverChildClass();
// loop through fields of childClass using reflection and assign
for (// all fields of childClass) {
childClass.setWhateverField(record.get(fileHeader[i]));
}
list.add(childClass);
System.out.println(p);
ps.add(p);
}
}
...
return list;
}
}
on one of the child classes, say ChildA
class ChildA extends CSVUtil {
// fields, getters, setters
}
How do I code the CSVUtil such that I can determine in runtime the child class in readCSV defined in the parent class?
Is it possible to make this method static and still be inherited?
As an alternative, is there API in Apache Commons CSV that can generally read a CSV, determine its schema, and wrap it as a generic Object (I don't know if I make sense here), and return a list of whatever that Object is ?
You want that readCSV to be a static method ?
Then, i would say that ChildA class shouldn't inherit from CSVUtil, but implement an Interface ... something like that :
public final class CSVUtil {
private CSVUtil() {
}
public static <T extends ICSV> List<T> readCSV(String filename) {
...
}
class ChildA implements ICSV
For the following class:
module LayoutEngine {
enum DocumentFormat {
DOCX = 1
};
export class DocHeader {
public format : DocumentFormat;
}
}
I have two questions:
The above has a compile error where it says "Public property
'format' of exported class has or is using private type
'DocumentFormat'." but a declaration of public before the enum is
also an error. So how do I do this?
Is there a way to place the enum declaration inside the class? Just a module name isn't great for namespacing as I have a lot of classes in that module.
thanks - dave
The above has a compile error where it says "Public property 'format' of exported class has or is using private type 'DocumentFormat'.
Simply export :
module LayoutEngine {
export enum DocumentFormat {
DOCX = 1
};
export class DocHeader {
public format : DocumentFormat;
}
}
Is there a way to place the enum declaration inside the class?
the enum typescript type needs to be at a module level (a file or inside a module). Of course if you want it inside the class just use a json object
module LayoutEngine {
export class DocHeader {
DocumentFormat = {
DOCX: 1
};
public format : number;
}
}
I'm looking into the possibilities to do TDD with TypeScript.
If I write my tests in TypeScript, is it possible to make the import statements return mocks for my class under test?
Or is the only feasible approach to write the tests in pure javascript and deal with injecting AMDs myself?
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
I use infuse.js for Dependency Injection in TypeScript.
Reference the d.ts
/// <reference path="definition/infusejs/infusejs.d.ts"/>
Initialize your injector at startup
this.injector = new infuse.Injector();
Map Dependencies
this.injector.mapClass( 'TodoController', TodoController );
this.injector.mapClass( 'TodoView', TodoView );
this.injector.mapClass( 'TodoModel', TodoModel, true ); // 'true' Map as singleton
Inject Dependencies
export class TodoController
{
static inject = ['TodoView', 'TodoModel'];
constructor( todoView:TodoView, todoModel:TodoModel )
{
}
}
It's string based as opposed to being type based (as reflection isn't yet possible in TypeScript). Despite that, it works very well in my applications.
Try this Dependency Injector (Typejector)
GitHub Typejector
With new TypeScript 1.5 it is possible using annotation way
For example
#injection
class SingletonClass {
public cat: string = "Kitty";
public dog: string = "Hot";
public say() {
alert(`${this.cat}-Cat and ${this.dog}-Dog`);
}
}
#injection
class SimpleClass {
public say(something: string) {
alert(`You said ${something}?`);
}
}
#resolve
class NeedInjectionsClass {
#inject(SingletonClass)
public helper: SingletonClass;
#inject(SimpleClass)
public simpleHelper: SimpleClass;
constructor() {
this.helper.say();
this.simpleHelper.say("wow");
}
}
class ChildClass extends NeedInjectionsClass {
}
var needInjection = new ChildClass();
For question case:
some property should realise pseudo Interface (or abstract class) like in next example.
class InterfaceClass {
public cat: string;
public dog: string;
public say() {
}
}
#injection(true, InterfaceClass)
class SingletonClass extends InterfaceClass {
public cat: string = "Kitty";
public dog: string = "Hot";
public say() {
alert(`${this.cat}-Cat and ${this.dog}-Dog`);
}
}
#injection(true, InterfaceClass)
class MockInterfaceClass extends InterfaceClass {
public cat: string = "Kitty";
public dog: string = "Hot";
public say() {
alert(`Mock-${this.cat}-Cat and Mock-${this.dog}-Dog`);
}
}
#injection
class SimpleClass {
public say(something: string) {
alert(`You said ${something}?`);
}
}
#resolve
class NeedInjectionsClass {
#inject(InterfaceClass)
public helper: InterfaceClass;
#inject(SimpleClass)
public simpleHelper: SimpleClass;
constructor() {
this.helper.say();
this.simpleHelper.say("wow");
}
}
class ChildClass extends NeedInjectionsClass {
}
var needInjection = new ChildClass();
Note: Mock injection should define after source code, because it mast redefine class-creator for interface
For people who use Angular2 I have developed Fluency Injection https://www.npmjs.com/package/fluency-injection. The documentation is quite complete and it mimics the behaviour of Angular2's DI.
Feedback is much appreciated and I hope it helps you :)
You can use the solution:
Lightweight dependency injection container for JavaScript/TypeScript
import {autoInjectable, container} from "tsyringe";
class MyService {
move(){
console.log('myService move 123', );
}
}
class MyServiceMock {
move(){
console.log('mock myService move 777', );
}
}
#autoInjectable()
export class ClassA {
constructor(public service?: MyService) {
}
move(){
this.service?.move();
}
}
container.register(MyService, {
useClass: MyServiceMock
});
new ClassA().move();
output:
mock myService move 777
I've been developing a DI solution called Pigly. An example given the original question regarding injecting and testing (admittedly not automatic-mock generation - although you could try ts-auto-mock as I've done here):
Given:
interface IDb {
set(key: string, value: string);
}
interface IApi {
setName(name: string);
}
class Api implements IApi {
constructor(private db: IDb) {}
setName(name: string){
this.db.set("name", name);
}
}
We can bind the types with,
import { Kernel, toSelf, to, toConst } from 'pigly';
import * as sinon from 'sinon';
let spy = sinon.spy();
let kernel = new Kernel();
kernel.bind(toSelf(Api));
kernel.bind<IApi>(to<Api>());
kernel.bind<IDb>(toConst({ set: spy }));
then resolve and test with:
let api = kernel.get<IApi>();
api.setName("John");
console.log(spy.calledWith("name", "John"));
execution/compilation of this example requires a typescript transformer - to compile the interface-symbols and constructor provider into plain javascript. There are a few ways to do this. The ts-node + ttypescript approach is to have a tsconfig.json:
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"moduleResolution": "node",
"plugins": [{
"transform": "#pigly/transformer"
}]
}
}
and execute with
ts-node --compiler ttypescript example-mock.ts
Pigly has the distinction of not requiring any changes to your (or third-party) classes, at the expense of either the use of a typescript transformer, or more verbose binding if (you don't want to use the transformer). Its still experimental, but I think it shows promise.
TypeScript works well with AMD loaders like requirejs. If confgured properly, TypeScript will output fully AMD compliant javascript.
In a testing situation, you could configure requirejs to inject testable modules.
You can give this a shot: https://www.npmjs.com/package/easy-injectionjs. It is a generic use dependency injection package.
#EasySingleton creates a single instance of the dependency through the entire application. It is ideal for a service of some sort.
#EasyPrototype creates as many instances of the dependency as needed. It is ideal for changeable dependencies.
#EasyFactory is primarily used for inheritance:
You can do anything using this package:
Simple usage (Coming from the readme):
import { Easy, EasyFactory, EasyPrototype, EasySingleton } from 'easy-injectionjs';
#EasyFactory()
abstract class Person {
abstract getName();
abstract setName(v: string);
}
// #EasyObservable()
#EasySingleton()
class Somebody extends Person{
// #Easy()
constructor (private name: string) {
super()
this.name = 'Sal';
}
public getName() {
return this.name;
}
public setName(v: string) {
this.name = v;
}
}
#EasyPrototype()
class Nobody extends Person{
#Easy()
somebody: Person;
constructor () {
super()
}
public getName() {
return this.somebody.getName();
}
public setName(v: string) {
this.somebody.setName(v);
}
}
#EasyPrototype()
class Data {
#Easy()
somebody: Person;
name: string;
change(v: string) {
this.somebody.setName(v);
}
getName(): string {
return this.somebody.getName();
}
}
let n = new Nobody();
console.log(n.getName()) // Prints Sal
n.setName('awesome');
console.log(n.getName()) // Prints awesome
let d = new Data()
console.log(d.getName()) // Prints awesome
d.change('Gelba')
console.log(n.getName()) // Prints Gelba
d.change('kaa')
console.log(n.getName()) // Prints Kaa
Even if you want to inject node modules you can do this:
import * as IExpress from 'express';
import { Easy, EasySingleton } from 'easy-injectionjs';
#EasySingleton()
class Express extends IExpress {}
#EasySingleton()
export class App {
#Easy()
private _express: Express;
}
let app = new App();
console.log(app)
Of course, the usage of the express server isn't for console logging. It is just for testing :D.
Hope that helps :D
Dime is a very simple dependency injection library. It's very early into development, though, so it probably has some bugs. There is more information on the wiki page.
Example usage:
import { ItemsService } from './items-service'; // ItemsService is an interface
import { Inject } from '#coined/dime';
class ItemsWidget {
#Inject()
private itemsService: ItemsService;
render() {
this.itemsService.getItems().subscribe(items => {
// ...
});
}
}
// Setup
const appPackage = new Package("App", {
token: "itemsService",
provideClass: AmazonItemsService // AmazonItemsService implements ItemsService
});
Dime.mountPackages(appPackage);
// Display the widget
const widget = new ItemsWidget();
widget.render();
I work on AutoFixtureTS that is inspired by AutoFixture. AutoFixtureTS makes it easier for TypeScript developers to do Test-Driven Development by automating non-relevant Test Fixture Setup, allowing the Test Developer to focus on the essentials of each test case.
http://ronniehegelund.github.io/AutoFixtureTS/
Its still just prototype code, but check it out :-)
/ronnie