Updated Angel Container to Null Safety
This commit is contained in:
parent
5a1782efba
commit
aefe1f1ab8
12 changed files with 79 additions and 78 deletions
|
@ -3,10 +3,11 @@
|
|||
* Updated pretty_logging to 3.0.0
|
||||
* Updated angel_http_exception to 3.0.0
|
||||
* Moved angel_cli to https://github.com/dukefirehawk/cli
|
||||
* Added code_buffer 2.0.0
|
||||
* Added combinator 2.0.0
|
||||
* Added code_buffer and updated to 2.0.0
|
||||
* Added combinator and updated to 2.0.0
|
||||
* Updated angel_route to 5.0.0
|
||||
* Updated angel_model to 3.0.0
|
||||
* Updated angel_container to 3.0.0
|
||||
|
||||
# 3.0.0 (Non NNBD)
|
||||
* Changed Dart SDK requirements for all packages to ">=2.10.0 <3.0.0"
|
||||
|
|
|
@ -21,14 +21,14 @@ Future<void> main() async {
|
|||
});
|
||||
|
||||
// Use `make` to create an instance.
|
||||
var truck = container.make<Truck>();
|
||||
var truck = container.make<Truck>()!;
|
||||
|
||||
// You can also resolve injections asynchronously.
|
||||
container.registerFactory<Future<int>>((_) async => 24);
|
||||
print(await container.makeAsync<int>());
|
||||
|
||||
// Asynchronous resolution also works for plain objects.
|
||||
await container.makeAsync<Truck>().then((t) => t.drive());
|
||||
await container.makeAsync<Truck>()!.then((t) => t.drive());
|
||||
|
||||
// Register a named singleton.
|
||||
container.registerNamedSingleton('the_truck', truck);
|
||||
|
@ -37,7 +37,7 @@ Future<void> main() async {
|
|||
truck.drive();
|
||||
|
||||
// Should print the same.
|
||||
container.findByName<Truck>('the_truck').drive();
|
||||
container.findByName<Truck>('the_truck')!.drive();
|
||||
|
||||
// We can make a child container with its own factory.
|
||||
var childContainer = container.createChild();
|
||||
|
@ -47,10 +47,10 @@ Future<void> main() async {
|
|||
});
|
||||
|
||||
// Make a truck with 5666 HP.
|
||||
childContainer.make<Truck>().drive();
|
||||
childContainer.make<Truck>()!.drive();
|
||||
|
||||
// However, calling `make<Engine>` will return the Engine singleton we created above.
|
||||
print(childContainer.make<Engine>().horsePower);
|
||||
print(childContainer.make<Engine>()!.horsePower);
|
||||
}
|
||||
|
||||
abstract class Truck {
|
||||
|
@ -64,12 +64,12 @@ class Engine {
|
|||
}
|
||||
|
||||
class _TruckImpl implements Truck {
|
||||
final Engine engine;
|
||||
final Engine? engine;
|
||||
|
||||
_TruckImpl(this.engine);
|
||||
|
||||
@override
|
||||
void drive() {
|
||||
print('Vroom! I have ${engine.horsePower} horsepower in my engine.');
|
||||
print('Vroom! I have ${engine!.horsePower} horsepower in my engine.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ class Container {
|
|||
final Map<Type, dynamic> _singletons = {};
|
||||
final Map<Type, dynamic Function(Container)> _factories = {};
|
||||
final Map<String, dynamic> _namedSingletons = {};
|
||||
final Container _parent;
|
||||
final Container? _parent;
|
||||
|
||||
Container(this.reflector) : _parent = null;
|
||||
|
||||
Container._child(this._parent) : reflector = _parent.reflector;
|
||||
Container._child(Container this._parent) : reflector = _parent.reflector;
|
||||
|
||||
bool get isRoot => _parent == null;
|
||||
|
||||
|
@ -23,8 +23,8 @@ class Container {
|
|||
}
|
||||
|
||||
/// Determines if the container has an injection of the given type.
|
||||
bool has<T>([Type t]) {
|
||||
var search = this;
|
||||
bool has<T>([Type? t]) {
|
||||
Container? search = this;
|
||||
t ??= T == dynamic ? t : T;
|
||||
|
||||
while (search != null) {
|
||||
|
@ -42,7 +42,7 @@ class Container {
|
|||
|
||||
/// Determines if the container has a named singleton with the given [name].
|
||||
bool hasNamed(String name) {
|
||||
var search = this;
|
||||
Container? search = this;
|
||||
|
||||
while (search != null) {
|
||||
if (search._namedSingletons.containsKey(name)) {
|
||||
|
@ -59,9 +59,9 @@ class Container {
|
|||
///
|
||||
/// It is similar to [make], but resolves an injection of either
|
||||
/// `Future<T>` or `T`.
|
||||
Future<T> makeAsync<T>([Type type]) {
|
||||
Future<T>? makeAsync<T>([Type? type]) {
|
||||
type ??= T;
|
||||
Type futureType; //.Future<T>.value(null).runtimeType;
|
||||
Type? futureType; //.Future<T>.value(null).runtimeType;
|
||||
|
||||
if (T == dynamic) {
|
||||
try {
|
||||
|
@ -87,18 +87,18 @@ class Container {
|
|||
///
|
||||
/// In contexts where a static generic type cannot be used, use
|
||||
/// the [type] argument, instead of [T].
|
||||
T make<T>([Type type]) {
|
||||
T? make<T>([Type? type]) {
|
||||
type ??= T;
|
||||
|
||||
var search = this;
|
||||
Container? search = this;
|
||||
|
||||
while (search != null) {
|
||||
if (search._singletons.containsKey(type)) {
|
||||
// Find a singleton, if any.
|
||||
return search._singletons[type] as T;
|
||||
return search._singletons[type] as T?;
|
||||
} else if (search._factories.containsKey(type)) {
|
||||
// Find a factory, if any.
|
||||
return search._factories[type](this) as T;
|
||||
return search._factories[type]!(this) as T?;
|
||||
} else {
|
||||
search = search._parent;
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ class Container {
|
|||
|
||||
var constructor = reflectedType.constructors.firstWhere(
|
||||
(c) => isDefault(c.name),
|
||||
orElse: () => throw ReflectionException(
|
||||
'${reflectedType.name} has no default constructor, and therefore cannot be instantiated.'));
|
||||
orElse: (() => throw ReflectionException(
|
||||
'${reflectedType.name} has no default constructor, and therefore cannot be instantiated.')) as ReflectedFunction Function()?);
|
||||
|
||||
for (var param in constructor.parameters) {
|
||||
var value = make(param.type.reflectedType);
|
||||
|
@ -131,7 +131,7 @@ class Container {
|
|||
return reflectedType.newInstance(
|
||||
isDefault(constructor.name) ? '' : constructor.name,
|
||||
positional,
|
||||
named, []).reflectee as T;
|
||||
named, []).reflectee as T?;
|
||||
} else {
|
||||
throw ReflectionException(
|
||||
'$type is not a class, and therefore cannot be instantiated.');
|
||||
|
@ -144,7 +144,7 @@ class Container {
|
|||
///
|
||||
/// Returns [f].
|
||||
T Function(Container) registerLazySingleton<T>(T Function(Container) f,
|
||||
{Type as}) {
|
||||
{Type? as}) {
|
||||
return registerFactory<T>(
|
||||
(container) {
|
||||
var r = f(container);
|
||||
|
@ -159,7 +159,7 @@ class Container {
|
|||
/// type within *this* container will return the result of [f].
|
||||
///
|
||||
/// Returns [f].
|
||||
T Function(Container) registerFactory<T>(T Function(Container) f, {Type as}) {
|
||||
T Function(Container) registerFactory<T>(T Function(Container) f, {Type? as}) {
|
||||
as ??= T;
|
||||
|
||||
if (_factories.containsKey(as)) {
|
||||
|
@ -174,7 +174,7 @@ class Container {
|
|||
/// type within *this* container will return [object].
|
||||
///
|
||||
/// Returns [object].
|
||||
T registerSingleton<T>(T object, {Type as}) {
|
||||
T registerSingleton<T>(T object, {Type? as}) {
|
||||
as ??= T == dynamic ? as : T;
|
||||
|
||||
if (_singletons.containsKey(as ?? object.runtimeType)) {
|
||||
|
@ -192,11 +192,11 @@ class Container {
|
|||
///
|
||||
/// [findByName] is best reserved for internal logic that end users of code should
|
||||
/// not see.
|
||||
T findByName<T>(String name) {
|
||||
T? findByName<T>(String name) {
|
||||
if (_namedSingletons.containsKey(name)) {
|
||||
return _namedSingletons[name] as T;
|
||||
return _namedSingletons[name] as T?;
|
||||
} else if (_parent != null) {
|
||||
return _parent.findByName<T>(name);
|
||||
return _parent!.findByName<T>(name);
|
||||
} else {
|
||||
throw StateError(
|
||||
'This container does not have a singleton named "$name".');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import '../../angel_container.dart';
|
||||
|
||||
final Map<Symbol, String> _symbolNames = <Symbol, String>{};
|
||||
final Map<Symbol, String?> _symbolNames = <Symbol, String?>{};
|
||||
|
||||
/// A [Reflector] implementation that performs no actual reflection,
|
||||
/// instead returning empty objects on every invocation.
|
||||
|
@ -13,9 +13,9 @@ class EmptyReflector extends Reflector {
|
|||
const EmptyReflector();
|
||||
|
||||
@override
|
||||
String getName(Symbol symbol) {
|
||||
String? getName(Symbol symbol) {
|
||||
return _symbolNames.putIfAbsent(
|
||||
symbol, () => symbolRegex.firstMatch(symbol.toString()).group(1));
|
||||
symbol, () => symbolRegex.firstMatch(symbol.toString())!.group(1));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -52,13 +52,13 @@ class _EmptyReflectedClass extends ReflectedClass {
|
|||
@override
|
||||
ReflectedInstance newInstance(
|
||||
String constructorName, List positionalArguments,
|
||||
[Map<String, dynamic> namedArguments, List<Type> typeArguments]) {
|
||||
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
|
||||
throw UnsupportedError(
|
||||
'Classes reflected via an EmptyReflector cannot be instantiated.');
|
||||
}
|
||||
|
||||
@override
|
||||
bool isAssignableTo(ReflectedType other) {
|
||||
bool isAssignableTo(ReflectedType? other) {
|
||||
return other == this;
|
||||
}
|
||||
|
||||
|
@ -75,13 +75,13 @@ class _EmptyReflectedType extends ReflectedType {
|
|||
@override
|
||||
ReflectedInstance newInstance(
|
||||
String constructorName, List positionalArguments,
|
||||
[Map<String, dynamic> namedArguments, List<Type> typeArguments]) {
|
||||
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
|
||||
throw UnsupportedError(
|
||||
'Types reflected via an EmptyReflector cannot be instantiated.');
|
||||
}
|
||||
|
||||
@override
|
||||
bool isAssignableTo(ReflectedType other) {
|
||||
bool isAssignableTo(ReflectedType? other) {
|
||||
return other == this;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ class _ReflectedTypeMirror extends ReflectedType {
|
|||
);
|
||||
|
||||
@override
|
||||
bool isAssignableTo(ReflectedType other) {
|
||||
bool isAssignableTo(ReflectedType? other) {
|
||||
if (other is _ReflectedClassMirror) {
|
||||
return mirror.isAssignableTo(other.mirror);
|
||||
} else if (other is _ReflectedTypeMirror) {
|
||||
|
@ -98,7 +98,7 @@ class _ReflectedTypeMirror extends ReflectedType {
|
|||
@override
|
||||
ReflectedInstance newInstance(
|
||||
String constructorName, List positionalArguments,
|
||||
[Map<String, dynamic> namedArguments, List<Type> typeArguments]) {
|
||||
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
|
||||
throw ReflectionException(
|
||||
'$name is not a class, and therefore cannot be instantiated.');
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ class _ReflectedClassMirror extends ReflectedClass {
|
|||
List<ReflectedFunction> get constructors => _constructorsOf(mirror);
|
||||
|
||||
@override
|
||||
bool isAssignableTo(ReflectedType other) {
|
||||
bool isAssignableTo(ReflectedType? other) {
|
||||
if (other is _ReflectedClassMirror) {
|
||||
return mirror.isAssignableTo(other.mirror);
|
||||
} else if (other is _ReflectedTypeMirror) {
|
||||
|
@ -167,7 +167,7 @@ class _ReflectedClassMirror extends ReflectedClass {
|
|||
@override
|
||||
ReflectedInstance newInstance(
|
||||
String constructorName, List positionalArguments,
|
||||
[Map<String, dynamic> namedArguments, List<Type> typeArguments]) {
|
||||
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
|
||||
return _ReflectedInstanceMirror(
|
||||
mirror.newInstance(Symbol(constructorName), positionalArguments));
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ class _ReflectedInstanceMirror extends ReflectedInstance {
|
|||
|
||||
class _ReflectedMethodMirror extends ReflectedFunction {
|
||||
final dart.MethodMirror mirror;
|
||||
final dart.ClosureMirror closureMirror;
|
||||
final dart.ClosureMirror? closureMirror;
|
||||
|
||||
_ReflectedMethodMirror(this.mirror, [this.closureMirror])
|
||||
: super(
|
||||
|
@ -242,7 +242,7 @@ class _ReflectedMethodMirror extends ReflectedFunction {
|
|||
'This object was reflected without a ClosureMirror, and therefore cannot be directly invoked.');
|
||||
}
|
||||
|
||||
return _ReflectedInstanceMirror(closureMirror.invoke(invocation.memberName,
|
||||
return _ReflectedInstanceMirror(closureMirror!.invoke(invocation.memberName,
|
||||
invocation.positionalArguments, invocation.namedArguments));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@ import 'package:quiver/core.dart';
|
|||
abstract class Reflector {
|
||||
const Reflector();
|
||||
|
||||
String getName(Symbol symbol);
|
||||
String? getName(Symbol symbol);
|
||||
|
||||
ReflectedClass reflectClass(Type clazz);
|
||||
ReflectedClass? reflectClass(Type clazz);
|
||||
|
||||
ReflectedFunction reflectFunction(Function function);
|
||||
ReflectedFunction? reflectFunction(Function function);
|
||||
|
||||
ReflectedType reflectType(Type type);
|
||||
ReflectedType? reflectType(Type type);
|
||||
|
||||
ReflectedInstance reflectInstance(Object object);
|
||||
ReflectedInstance? reflectInstance(Object object);
|
||||
|
||||
ReflectedType reflectFutureOf(Type type) {
|
||||
throw UnsupportedError('`reflectFutureOf` requires `dart:mirrors`.');
|
||||
|
@ -22,7 +22,7 @@ abstract class Reflector {
|
|||
abstract class ReflectedInstance {
|
||||
final ReflectedType type;
|
||||
final ReflectedClass clazz;
|
||||
final Object reflectee;
|
||||
final Object? reflectee;
|
||||
|
||||
const ReflectedInstance(this.type, this.clazz, this.reflectee);
|
||||
|
||||
|
@ -56,9 +56,9 @@ abstract class ReflectedType {
|
|||
|
||||
ReflectedInstance newInstance(
|
||||
String constructorName, List positionalArguments,
|
||||
[Map<String, dynamic> namedArguments, List<Type> typeArguments]);
|
||||
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]);
|
||||
|
||||
bool isAssignableTo(ReflectedType other);
|
||||
bool isAssignableTo(ReflectedType? other);
|
||||
}
|
||||
|
||||
abstract class ReflectedClass extends ReflectedType {
|
||||
|
@ -94,7 +94,7 @@ abstract class ReflectedClass extends ReflectedType {
|
|||
class ReflectedDeclaration {
|
||||
final String name;
|
||||
final bool isStatic;
|
||||
final ReflectedFunction function;
|
||||
final ReflectedFunction? function;
|
||||
|
||||
const ReflectedDeclaration(this.name, this.isStatic, this.function);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class StaticReflector extends Reflector {
|
|||
this.instances = const {}});
|
||||
|
||||
@override
|
||||
String getName(Symbol symbol) {
|
||||
String? getName(Symbol symbol) {
|
||||
if (!names.containsKey(symbol)) {
|
||||
throw ArgumentError(
|
||||
'The value of $symbol is unknown - it was not generated.');
|
||||
|
@ -26,11 +26,11 @@ class StaticReflector extends Reflector {
|
|||
}
|
||||
|
||||
@override
|
||||
ReflectedClass reflectClass(Type clazz) =>
|
||||
reflectType(clazz) as ReflectedClass;
|
||||
ReflectedClass? reflectClass(Type clazz) =>
|
||||
reflectType(clazz) as ReflectedClass?;
|
||||
|
||||
@override
|
||||
ReflectedFunction reflectFunction(Function function) {
|
||||
ReflectedFunction? reflectFunction(Function function) {
|
||||
if (!functions.containsKey(function)) {
|
||||
throw ArgumentError(
|
||||
'There is no reflection information available about $function.');
|
||||
|
@ -40,7 +40,7 @@ class StaticReflector extends Reflector {
|
|||
}
|
||||
|
||||
@override
|
||||
ReflectedInstance reflectInstance(Object object) {
|
||||
ReflectedInstance? reflectInstance(Object object) {
|
||||
if (!instances.containsKey(object)) {
|
||||
throw ArgumentError(
|
||||
'There is no reflection information available about $object.');
|
||||
|
@ -50,7 +50,7 @@ class StaticReflector extends Reflector {
|
|||
}
|
||||
|
||||
@override
|
||||
ReflectedType reflectType(Type type) {
|
||||
ReflectedType? reflectType(Type type) {
|
||||
if (!types.containsKey(type)) {
|
||||
throw ArgumentError(
|
||||
'There is no reflection information available about $type.');
|
||||
|
|
|
@ -17,7 +17,7 @@ class ThrowingReflector extends Reflector {
|
|||
const ThrowingReflector({this.errorMessage = defaultErrorMessage});
|
||||
|
||||
@override
|
||||
String getName(Symbol symbol) => const EmptyReflector().getName(symbol);
|
||||
String? getName(Symbol symbol) => const EmptyReflector().getName(symbol);
|
||||
|
||||
UnsupportedError _error() => UnsupportedError(errorMessage);
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
name: angel_container
|
||||
version: 2.0.0
|
||||
version: 3.0.0
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
description: A hierarchical DI container, and pluggable backends for reflection.
|
||||
homepage: https://github.com/angel-dart/container.git
|
||||
environment:
|
||||
sdk: ">=2.10.0 <3.0.0"
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
dependencies:
|
||||
collection: ^1.15.0
|
||||
quiver: ^2.1.5
|
||||
quiver: ^3.0.0
|
||||
dev_dependencies:
|
||||
pedantic: ^1.11.0
|
||||
test: ^1.16.5
|
||||
test: ^1.16.8
|
|
@ -7,7 +7,7 @@ void returnVoidFromAFunction(int x) {}
|
|||
|
||||
void testReflector(Reflector reflector) {
|
||||
var blaziken = Pokemon('Blaziken', PokemonType.fire);
|
||||
Container container;
|
||||
late Container container;
|
||||
|
||||
setUp(() {
|
||||
container = Container(reflector);
|
||||
|
@ -16,7 +16,7 @@ void testReflector(Reflector reflector) {
|
|||
});
|
||||
|
||||
test('get field', () {
|
||||
var blazikenMirror = reflector.reflectInstance(blaziken);
|
||||
var blazikenMirror = reflector.reflectInstance(blaziken)!;
|
||||
expect(blazikenMirror.getField('type').reflectee, blaziken.type);
|
||||
});
|
||||
|
||||
|
@ -24,19 +24,19 @@ void testReflector(Reflector reflector) {
|
|||
var mirror = reflector.reflectFunction(returnVoidFromAFunction);
|
||||
|
||||
test('void return type returns dynamic', () {
|
||||
expect(mirror.returnType, reflector.reflectType(dynamic));
|
||||
expect(mirror!.returnType, reflector.reflectType(dynamic));
|
||||
});
|
||||
|
||||
test('counts parameters', () {
|
||||
expect(mirror.parameters, hasLength(1));
|
||||
expect(mirror!.parameters, hasLength(1));
|
||||
});
|
||||
|
||||
test('counts types parameters', () {
|
||||
expect(mirror.typeParameters, isEmpty);
|
||||
expect(mirror!.typeParameters, isEmpty);
|
||||
});
|
||||
|
||||
test('correctly reflects parameter types', () {
|
||||
var p = mirror.parameters[0];
|
||||
var p = mirror!.parameters[0];
|
||||
expect(p.name, 'x');
|
||||
expect(p.isRequired, true);
|
||||
expect(p.isNamed, false);
|
||||
|
@ -67,12 +67,12 @@ void testReflector(Reflector reflector) {
|
|||
});
|
||||
|
||||
test('constructor injects singleton', () {
|
||||
var lower = container.make<LowerPokemon>();
|
||||
var lower = container.make<LowerPokemon>()!;
|
||||
expect(lower.lowercaseName, blaziken.name.toLowerCase());
|
||||
});
|
||||
|
||||
test('newInstance works', () {
|
||||
var type = container.reflector.reflectType(Pokemon);
|
||||
var type = container.reflector.reflectType(Pokemon)!;
|
||||
var instance =
|
||||
type.newInstance('changeName', [blaziken, 'Charizard']).reflectee
|
||||
as Pokemon;
|
||||
|
@ -83,7 +83,7 @@ void testReflector(Reflector reflector) {
|
|||
|
||||
test('isAssignableTo', () {
|
||||
var pokemonType = container.reflector.reflectType(Pokemon);
|
||||
var kantoPokemonType = container.reflector.reflectType(KantoPokemon);
|
||||
var kantoPokemonType = container.reflector.reflectType(KantoPokemon)!;
|
||||
|
||||
expect(kantoPokemonType.isAssignableTo(pokemonType), true);
|
||||
expect(
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:angel_container/angel_container.dart';
|
|||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
Container container;
|
||||
late Container container;
|
||||
|
||||
setUp(() {
|
||||
container = Container(const EmptyReflector())
|
||||
|
@ -37,14 +37,14 @@ void main() {
|
|||
}
|
||||
|
||||
class Artist {
|
||||
final String name;
|
||||
final Song song;
|
||||
final String? name;
|
||||
final Song? song;
|
||||
|
||||
Artist({this.name, this.song});
|
||||
}
|
||||
|
||||
class Song {
|
||||
final String title;
|
||||
final String? title;
|
||||
|
||||
Song({this.title});
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'package:angel_container/angel_container.dart';
|
|||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
Container container;
|
||||
late Container container;
|
||||
|
||||
setUp(() {
|
||||
container = Container(const EmptyReflector());
|
||||
|
@ -10,7 +10,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('fetch by name', () {
|
||||
expect(container.findByName<Foo>('foo').bar, 'baz');
|
||||
expect(container.findByName<Foo>('foo')!.bar, 'baz');
|
||||
});
|
||||
|
||||
test('cannot redefine', () {
|
||||
|
@ -28,7 +28,7 @@ void main() {
|
|||
}
|
||||
|
||||
class Foo {
|
||||
final String bar;
|
||||
final String? bar;
|
||||
|
||||
Foo({this.bar});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue