Custom container in handleContained

This commit is contained in:
Tobe O 2018-10-21 04:00:39 -04:00
parent b1d685797e
commit 0d64e101f4
5 changed files with 33 additions and 15 deletions

View file

@ -1,3 +1,6 @@
# 2.0.0-alpha.6
* Allow passing a custom `Container` to `handleContained` and co.
# 2.0.0-alpha.5 # 2.0.0-alpha.5
* `MapService` methods now explicitly return `Map<String, dynamic>`. * `MapService` methods now explicitly return `Map<String, dynamic>`.

View file

@ -23,8 +23,9 @@ RequestHandler ioc(Function handler, {Iterable<String> optional: const []}) {
} }
resolveInjection(requirement, InjectionRequest injection, RequestContext req, resolveInjection(requirement, InjectionRequest injection, RequestContext req,
ResponseContext res, bool throwOnUnresolved) { ResponseContext res, bool throwOnUnresolved, [Container container]) {
var propFromApp; var propFromApp;
container ??= req?.container ?? res?.app?.container;
if (requirement == RequestContext) { if (requirement == RequestContext) {
return req; return req;
@ -56,11 +57,11 @@ resolveInjection(requirement, InjectionRequest injection, RequestContext req,
if (req.params.containsKey(key) || if (req.params.containsKey(key) ||
req.app.configuration.containsKey(key) || req.app.configuration.containsKey(key) ||
_primitiveTypes.contains(type)) { _primitiveTypes.contains(type)) {
return resolveInjection(key, injection, req, res, throwOnUnresolved); return resolveInjection(key, injection, req, res, throwOnUnresolved, container);
} else } else
return resolveInjection(type, injection, req, res, throwOnUnresolved); return resolveInjection(type, injection, req, res, throwOnUnresolved, container);
} else if (requirement is Type && requirement != dynamic) { } else if (requirement is Type && requirement != dynamic) {
return req.app.container.make(requirement); return container.make(requirement);
} else if (throwOnUnresolved) { } else if (throwOnUnresolved) {
throw new ArgumentError( throw new ArgumentError(
'$requirement cannot be injected into a request handler.'); '$requirement cannot be injected into a request handler.');
@ -78,7 +79,8 @@ bool suitableForInjection(
} }
/// Handles a request with a DI-enabled handler. /// Handles a request with a DI-enabled handler.
RequestHandler handleContained(Function handler, InjectionRequest injection) { RequestHandler handleContained(Function handler, InjectionRequest injection,
[Container container]) {
return (RequestContext req, ResponseContext res) { return (RequestContext req, ResponseContext res) {
if (injection.parameters.isNotEmpty && if (injection.parameters.isNotEmpty &&
injection.parameters.values.any((p) => p.match != null) && injection.parameters.values.any((p) => p.match != null) &&
@ -89,11 +91,12 @@ RequestHandler handleContained(Function handler, InjectionRequest injection) {
Map<Symbol, dynamic> named = {}; Map<Symbol, dynamic> named = {};
args.addAll(injection.required args.addAll(injection.required
.map((r) => resolveInjection(r, injection, req, res, true))); .map((r) => resolveInjection(r, injection, req, res, true, container)));
injection.named.forEach((k, v) { injection.named.forEach((k, v) {
var name = new Symbol(k); var name = new Symbol(k);
named[name] = resolveInjection([k, v], injection, req, res, false); named[name] =
resolveInjection([k, v], injection, req, res, false, container);
}); });
return Function.apply(handler, args, named); return Function.apply(handler, args, named);

View file

@ -306,24 +306,26 @@ class Angel extends Routable {
/// Run a function after injecting from service container. /// Run a function after injecting from service container.
/// If this function has been reflected before, then /// If this function has been reflected before, then
/// the execution will be faster, as the injection requirements were stored beforehand. /// the execution will be faster, as the injection requirements were stored beforehand.
Future runContained( Future runContained(Function handler, RequestContext req, ResponseContext res,
Function handler, RequestContext req, ResponseContext res) { [Container container]) {
return new Future.sync(() { return new Future.sync(() {
if (_preContained.containsKey(handler)) { if (_preContained.containsKey(handler)) {
return handleContained(handler, _preContained[handler])(req, res); return handleContained(handler, _preContained[handler], container)(
req, res);
} }
return runReflected(handler, req, res); return runReflected(handler, req, res, container);
}); });
} }
/// Runs with DI, and *always* reflects. Prefer [runContained]. /// Runs with DI, and *always* reflects. Prefer [runContained].
Future runReflected( Future runReflected(Function handler, RequestContext req, ResponseContext res,
Function handler, RequestContext req, ResponseContext res) { [Container container]) {
var h = handleContained( var h = handleContained(
handler, handler,
_preContained[handler] = _preContained[handler] =
preInject(handler, req.app.container.reflector)); preInject(handler, req.app.container.reflector),
container);
return new Future.sync(() => h(req, res)); return new Future.sync(() => h(req, res));
// return closureMirror.apply(args).reflectee; // return closureMirror.apply(args).reflectee;
} }

View file

@ -1,5 +1,5 @@
name: angel_framework name: angel_framework
version: 2.0.0-alpha.5 version: 2.0.0-alpha.6
description: > description: >
A high-powered HTTP server with DI, routing and more. A high-powered HTTP server with DI, routing and more.
When combined with the other packages in the Angel ecosystem, this When combined with the other packages in the Angel ecosystem, this

View file

@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:angel_container/angel_container.dart';
import 'package:angel_container/mirrors.dart'; import 'package:angel_container/mirrors.dart';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
@ -44,6 +45,15 @@ main() {
await server.close(force: true); await server.close(force: true);
}); });
test('runContained with custom container', () async {
var app = new Angel();
var c = new Container(const EmptyReflector());
c.registerSingleton(new Todo(text: 'Hey!'));
var r = await app.runContained((Todo t) => t, null, null, c);
expect(r, c);
});
test("singleton in route", () async { test("singleton in route", () async {
validateTodoSingleton(await client.get("$url/errands")); validateTodoSingleton(await client.get("$url/errands"));
}); });