2.0.0-rc.4 (async injections)
This commit is contained in:
parent
106a5683dd
commit
09ff68f5ad
4 changed files with 54 additions and 12 deletions
|
@ -1,3 +1,7 @@
|
|||
# 2.0.0-rc.4
|
||||
* Support resolution of asynchronous injections in controllers and `ioc`.
|
||||
* Inject `RequestContext` and `ResponseContext` into requests.
|
||||
|
||||
# 2.0.0-rc.3
|
||||
* `MapService.modify` was not actually modifying items.
|
||||
|
||||
|
|
|
@ -122,6 +122,8 @@ abstract class Driver<
|
|||
req.params.addAll(tuple.item2);
|
||||
|
||||
req.container
|
||||
..registerSingleton<RequestContext>(req)
|
||||
..registerSingleton<ResponseContext>(res)
|
||||
..registerSingleton<MiddlewarePipeline>(tuple.item4)
|
||||
..registerSingleton<MiddlewarePipeline<RequestHandler>>(line)
|
||||
..registerSingleton<MiddlewarePipelineIterator>(it)
|
||||
|
|
|
@ -24,7 +24,7 @@ RequestHandler ioc(Function handler, {Iterable<String> optional = const []}) {
|
|||
|
||||
resolveInjection(requirement, InjectionRequest injection, RequestContext req,
|
||||
ResponseContext res, bool throwOnUnresolved,
|
||||
[Container container]) {
|
||||
[Container container]) async {
|
||||
var propFromApp;
|
||||
container ??= req?.container ?? res?.app?.container;
|
||||
|
||||
|
@ -60,12 +60,19 @@ resolveInjection(requirement, InjectionRequest injection, RequestContext req,
|
|||
if (req.params.containsKey(key) ||
|
||||
req.app.configuration.containsKey(key) ||
|
||||
_primitiveTypes.contains(type)) {
|
||||
return resolveInjection(
|
||||
return await resolveInjection(
|
||||
key, injection, req, res, throwOnUnresolved, container);
|
||||
} else
|
||||
return resolveInjection(
|
||||
return await resolveInjection(
|
||||
type, injection, req, res, throwOnUnresolved, container);
|
||||
} else if (requirement is Type && requirement != dynamic) {
|
||||
try {
|
||||
var futureType = container.reflector.reflectFutureOf(requirement);
|
||||
return await container.make(futureType.reflectedType);
|
||||
} on UnsupportedError {
|
||||
// Ignore this; it just means that the reflector doesn't support futures.
|
||||
}
|
||||
|
||||
return container.make(requirement);
|
||||
} else if (throwOnUnresolved) {
|
||||
throw new ArgumentError(
|
||||
|
@ -86,7 +93,7 @@ bool suitableForInjection(
|
|||
/// Handles a request with a DI-enabled handler.
|
||||
RequestHandler handleContained(Function handler, InjectionRequest injection,
|
||||
[Container container]) {
|
||||
return (RequestContext req, ResponseContext res) {
|
||||
return (RequestContext req, ResponseContext res) async {
|
||||
if (injection.parameters.isNotEmpty &&
|
||||
injection.parameters.values.any((p) => p.match != null) &&
|
||||
!suitableForInjection(req, res, injection))
|
||||
|
@ -95,14 +102,16 @@ RequestHandler handleContained(Function handler, InjectionRequest injection,
|
|||
List args = [];
|
||||
|
||||
Map<Symbol, dynamic> named = {};
|
||||
args.addAll(injection.required
|
||||
.map((r) => resolveInjection(r, injection, req, res, true, container)));
|
||||
|
||||
injection.named.forEach((k, v) {
|
||||
var name = new Symbol(k);
|
||||
named[name] =
|
||||
resolveInjection([k, v], injection, req, res, false, container);
|
||||
});
|
||||
for (var r in injection.required) {
|
||||
args.add(await resolveInjection(r, injection, req, res, true, container));
|
||||
}
|
||||
|
||||
for (var entry in injection.named.entries) {
|
||||
var name = new Symbol(entry.key);
|
||||
named[name] = await resolveInjection(
|
||||
[entry.key, entry.value], injection, req, res, false, container);
|
||||
}
|
||||
|
||||
return Function.apply(handler, args, named);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:angel_container/angel_container.dart';
|
||||
import 'package:angel_framework/http.dart';
|
||||
import 'package:angel_container/mirrors.dart';
|
||||
|
@ -26,12 +26,18 @@ main() {
|
|||
|
||||
// Inject some todos
|
||||
app.container.registerSingleton(new Todo(text: TEXT, over: OVER));
|
||||
app.container.registerFactory<Future<Foo>>((container) async {
|
||||
var req = container.make<RequestContext>();
|
||||
var text = await req.body.transform(utf8.decoder).join();
|
||||
return Foo(text);
|
||||
});
|
||||
|
||||
app.get("/errands", ioc((Todo singleton) => singleton));
|
||||
app.get(
|
||||
"/errands3",
|
||||
ioc(({Errand singleton, Todo foo, RequestContext req}) =>
|
||||
singleton.text));
|
||||
app.post('/async', ioc((Foo foo) => {'baz': foo.bar}));
|
||||
await app.configure(new SingletonController().configureServer);
|
||||
await app.configure(new ErrandController().configureServer);
|
||||
|
||||
|
@ -82,6 +88,16 @@ main() {
|
|||
var text = await json.decode(response.body) as String;
|
||||
expect(text, equals(TEXT));
|
||||
});
|
||||
|
||||
test('resolve from future in controller', () async {
|
||||
var response = await client.post('$url/errands4/async', body: 'hey');
|
||||
expect(response.body, json.encode({'bar': 'hey'}));
|
||||
});
|
||||
|
||||
test('resolve from future in route', () async {
|
||||
var response = await client.post('$url/async', body: 'yes');
|
||||
expect(response.body, json.encode({'baz': 'yes'}));
|
||||
});
|
||||
}
|
||||
|
||||
void validateTodoSingleton(response) {
|
||||
|
@ -103,6 +119,17 @@ class ErrandController extends Controller {
|
|||
errand(Errand errand) {
|
||||
return errand.text;
|
||||
}
|
||||
|
||||
@Expose('/async', method: 'POST')
|
||||
asyncResolve(Foo foo) {
|
||||
return {'bar': foo.bar};
|
||||
}
|
||||
}
|
||||
|
||||
class Foo {
|
||||
final String bar;
|
||||
|
||||
Foo(this.bar);
|
||||
}
|
||||
|
||||
class Errand {
|
||||
|
|
Loading…
Reference in a new issue