Angel3 Developer Guide
  • README
  • Foreword
  • Tutorial
    • Getting Started
    • Minimal Setup
  • Command Line Interface
    • Setup
  • Templates and Views
    • Server Side Rendered Views
    • JAEL3
      • About
      • Basics
      • Custom Elements
      • Strict Resolution
      • Directive: declare
      • Directive: for-each
      • Directive: extend
      • Directive: if
      • Directive: include
      • Directive: switch
  • Authentication
    • About
    • Strategies
    • Local
  • Databases
    • Object Relational Mapping (ORM)
      • About
      • Basic Functionality
      • Relations
      • Migrations
      • PostgreSQL
    • NoSQL
  • Extensions and Plugins
    • Using Plug-ins
    • Writing a Plugin
  • Under the hood
    • Basic Routing
    • Requests & Responses
    • Request Lifecycle
    • Dependency Injection
    • Middleware
    • Controllers
    • Parsing Request Bodies
    • Serialization
    • Service Basics
    • Testing
    • Error Handling
    • Pattern Matching and Parameter
  • Angel Framework Migration
    • Angel 2.x.x to Angel3
      • Rationale - Why a new Version?
      • Framework Changelog
      • 3.0.0 Migration Guide
    • Angel 1.x.x to 2.x.x
      • Framework Changelog
      • 2.0.0 Migration Guide
  • Packages
    • Authentication
    • CORS
    • Database-Agnostic Relations
    • Configuration
    • Databases
      • ORM
      • MongoDB
      • JSON File-based
      • RethinkDB
    • Templates and Views
      • Jael template engine
      • Mustache Templates
      • compiled_mustache-based engine
      • html_builder-based engine
      • Markdown template engine
      • Using Angel with Angular
    • Hot Reloading
    • Pagination
    • Polling
    • Production Utilities
    • REST Client
    • Reverse Proxy
    • Router
    • Serialization
    • Service Seeder
    • Static Files
    • Security
    • Server-sent Events
    • shelf Integration
    • Task Engine
    • User Agents
    • Validation
    • Websockets
  • Resources
    • Dependency Injection Patterns
    • Example Projects
    • YouTube Tutorials
    • Ecosystem
Powered by GitBook
On this page
  • Adding a Singleton
  • In Routes and Controllers
  • Dependency-Injected Controllers
  • Enabling dart:mirrors or other Reflection
  • Next Up

Was this helpful?

  1. Under the hood

Dependency Injection

PreviousRequest LifecycleNextMiddleware

Last updated 3 years ago

Was this helpful?

Angel3 uses a for DI. Dependency injection makes it easier to build applications with multiple moving parts, because logic can be contained in one location and reused at another place in your application.

Adding a Singleton

Future<void> myPlugin(Angel app) async  {
  app.container.registerSingleton(SomeClass("foo"));
  app.container.registerSingleton<SomeAbstractClass>(MyImplClass());
  app.container.registerFactory((_) => SomeClass("foo"));
  app.container.registerLazySingleton((_) => SomeOtherClass());
  app.container.registerNamedSingleton('yes', Yes());
}

You can also inject within a RequestContext, as each one has a controller property that extends from the app's global container.

Accessing these injected properties is easy, and strongly typed:

// Inject types.
var todo = req.container.make<Todo>();
print(todo.isComplete);

// Or by name
var db = await req.container.findByName<Db>('database');
var collection = db.collection('pets');

In Routes and Controllers

In Angel3, by wrapping a function in a call to ioc, you can automatically inject the dependencies of any route handler.

app.get("/some/class/text", ioc((SomeClass singleton) => singleton.text)); // Always "foo"

app.post("/foo", ioc((SomeClass singleton, {Foo optionalInjection}));

@Expose("/my/controller")
class MyController extends Controller {

  @Expose("/bar")
  // Inject classes from container, request parameters or the request/response context :)
  bar(SomeClass singleton, RequestContext req) => "${singleton.text} bar"; // Always "foo bar"

  @Expose("/baz")
  baz({Foo optionalInjection});
}

As you can imagine, this is very useful for managing things such as database connections.

configureServer(Angel app) async {
  var db = Db("mongodb://localhost:27017/db");
  await db.open();
  app.container.registerSingleton(db);
}

@Expose("/users")
class ApiController extends Controller {
  @Expose("/:id")
  fetchUser(String id, Db db) => db.collection("users").findOne(where.id(ObjectId.fromHexString(id)));
}

Dependency-Injected Controllers

Controllers have dependencies injected without any additional configuration by you. However, you might want to inject dependencies into the constructor of your controller.

@Expose('/controller')
class MyController {
  final AngelAuth auth;
  final Db db;

  MyController(this.auth, this.db);

  @Expose('/login')
  login() => auth.authenticate('local');
}

void main() async {
  // At some point in your application, register necessary dependencies as singletons...
  app.container.registerSingleton(auth);
  app.container.registerSingleton(db);

  // Create the controller with injected dependencies
  await app.mountController<MyController>();
}

Enabling dart:mirrors or other Reflection

By default, Angel3 will use the EmptyReflector() to power its Container instances, which has no support for dart:mirrors, so that it can be used in contexts where Dart reflection is not available.

However, by using a different Reflector, you can use the full power of Angel3's DI system. angel3 init projects use the MirrorsReflector() by default.

If your application is using any sort of functionality reliant on annotations or reflection, either include the MirrorsReflector, or use a static reflector variant.

The following use cases require reflection:

  • Use of Controllers, via @Expose() or @ExposeWS()

  • Use of dependency injection into constructors, whether in controllers or plain container.make calls

  • Use of the ioc function in any route

The MirrorsReflector from package:angel3_container/mirrors.dart is by far the most convenient pattern, so use it if possible.

However, the following alternatives exist:

  • Generation via package:angel3_container_generator

  • Creating an instance of StaticReflector

  • Manually implementing the Reflector interface (cumbersome; not recommended)

Next Up

Continue reading to learn about .

container hierarchy
Middleware