Code Monkey home page Code Monkey logo

cork's Introduction

cork

Build Status

A fast dependency injection framework and codegen engine for Dart.

Example:

import 'package:cork/cork.dart';

// "Inject" means that something can be created by an Injector.
@Inject()
class Foo {}

class CustomFooImpl implements Foo {}

// "Module" is a collection of Inject-ables, and other Modules.
// It can also provide custom factory functions.
@Module(const [Foo])
class FooModule {
  // Instead of using the default factory for Foo, use this function.
  @Provide(Foo)
  static Foo getFoo() => new CustomFooImpl();
}

Cork is built with static analysis and tree-shaking in mind. As such, unlike package:di, all bindings are declared via Dart metadata annotations.

It is possible to run Cork with either runtime or compile-time analysis, depending on your target platform, and even mix and match (i.e. use runtime reflection for development, and compile-time for production).

Running Cork

Reflective mode (using dart:mirrors)

Suitable for use in the Dart VM (e.g. server-side), or within Dartium for develpopment only.

import 'package:cork/dynamic.dart';

// Assume same file as above.
import 'foo.dart';

void main() {
  var injector = createInjector(FooModule);
  var foo = injector.get(Foo);
  assert(foo.runtimeType == CustomFooImpl)
}

Static mode

Disable reflection and use Cork in a production/static mode by analyzing your app and generating bindings.

NOTE: This is still experimental.

There are a few strategies:

Dynamic mode

To maintain API compatibility, it is possible to manually create an Injector with generated bindings:

import 'package:cork/cork.dart';

import 'foo.dart';
import 'foo_generated.dart' as generated;

void main() {
  var injector = new Injector(generated.bindingsForFooModule);
  var foo = injector.get(Foo);
  assert(foo.runtimeType == CustomFooImpl)
}
Background

The reflective mode of Cork uses mirrors to generate Binding objects:

abstract class Binding {
  /// Provider tuple for [T].
  final Provider<T> provider;

  /// The type of [T].
  final Type token;
}

Simply put, a Binding is a tuple between a Provider (factory) and a Type (token).

Generating bindings

The Cork binding generator can analyze an @Entrypoint, and generate a full list of bindings:

var foo = Uri.parse('package:cork/testing/integration/spec.dart');

// The dart file generated.
var generator = new BindingGenerator(anthology);
var result = await generator.generate(uri, 'SingleModuleEntrypoint');
// result.toSource() is a formatted file that looks like the code blob below.
final bindingsForSingleModuleEntrypoint = <Binding>[
  new Binding(Foo, new Provider((args) => new Foo(), const [])),
  new Binding(Bar, new Provider((args) => new Bar(args[0]), const [Foo]))
];

NOTE: A transformer will be available in an upcoming version. Right now it requires manual work.

Static mode:

It is easier to use the dynamic Injector, either with mirrors or with the binding generator, in most applications, because you are able to at runtime determine what to create a new instance of. However, there are performance penalities involved:

  • dart2js will only be able to treeshake method bodies, at best, because you refer to every injectable class
  • Factory functions are megamorphic.

For scenarios where you are able to take full advantage of a completely typed and static injector, Cork will help generate a typed injector specifically for your application. For example:

Generates a class called SingleModuleEntrypointInjector:

var foo = Uri.parse('package:cork/testing/integration/spec.dart');

// The dart file generated.
var generator = new ClassGenerator(anthology);
var result = await generator.generate(uri, 'SingleModuleEntrypoint');
// result.toSource() is a formatted file that looks like the code blob below.
class SingleModuleEntrypointInjector implements Injector {
  Foo _foo;
  Bar _bar;
  get(_) {
    throw new UnsupportedError(
        'Generated injector does not support dynamic get.');
  }

  Foo getFoo() {
    if (_foo == null) {
      _foo = new Foo();
    }
    return _foo;
  }

  Bar getBar() {
    if (_bar == null) {
      _bar = new Bar(getFoo());
    }
    return _bar;
  }
}

It's possible to use this injector directly like any other class in your code:

var injector = new SingleModuleEntrypointInjector();
var foo = injector.get1();
assert(foo.runtimeType == Foo);

Future plans

Ultimately, Cork will also supply source generation helpers to rewrite parts of your application to take use of the statically defined methods. Something like below is planned - it will run using mirrors in development mode.

@Entrypoint()
class Foo {
  final Injector _injector;
  
  Foo(this._injector);
  
  Bar getBar() => _injector.get(Bar);
}

void main() {
  var injector = createInjector(Foo);
  injector.getFoo().getBar();
}

And in static mode will be rewritten:

class Foo {
  final $GeneratedInjector _injector;
  
  Foo(this._injector);
  
  Bar getBar() => _injector.get2();
}

void main() {
  var injector = new $GeneratedInjector();
  injector.get1().getBar();
}

There are also adapters planned to use Cork in Angular 1.0 and Angular 2.0 applications.

cork's People

Contributors

matanlurey avatar

Watchers

 avatar  avatar

Forkers

eswarvarma-dev

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.