refactor: add factory() for deferred resolution working on wrap()
This commit is contained in:
parent
107266ca67
commit
0de4f37270
3 changed files with 595 additions and 0 deletions
|
@ -1157,6 +1157,73 @@ class Container {
|
||||||
bind(abstract).to(concrete);
|
bind(abstract).to(concrete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrap a closure with dependency injection
|
||||||
|
///
|
||||||
|
/// This allows you to wrap a closure so its dependencies will be injected when executed.
|
||||||
|
/// The wrapped closure will receive injected dependencies first, followed by any
|
||||||
|
/// additional parameters passed to the wrapper.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// var wrapped = container.wrap((Logger logger, String message) {
|
||||||
|
/// logger.log(message);
|
||||||
|
/// });
|
||||||
|
/// wrapped('Hello world'); // Logger will be injected automatically
|
||||||
|
/// ```
|
||||||
|
Function wrap<T extends Function>(T callback) {
|
||||||
|
return ([dynamic arg1]) {
|
||||||
|
// Get the function's parameter types through reflection
|
||||||
|
var reflectedFunction = reflector.reflectFunction(callback);
|
||||||
|
if (reflectedFunction == null) {
|
||||||
|
throw BindingResolutionException(
|
||||||
|
'Could not reflect function parameters for dependency injection');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve dependencies for each parameter
|
||||||
|
var resolvedArgs = <dynamic>[];
|
||||||
|
var namedArgs = <Symbol, dynamic>{};
|
||||||
|
|
||||||
|
// First resolve all container-injectable parameters
|
||||||
|
var injectedTypes = <Type>{};
|
||||||
|
for (var param in reflectedFunction.parameters) {
|
||||||
|
var paramType = param.type.reflectedType;
|
||||||
|
if (has(paramType)) {
|
||||||
|
if (param.isNamed) {
|
||||||
|
namedArgs[Symbol(param.name)] = make(paramType);
|
||||||
|
} else {
|
||||||
|
resolvedArgs.add(make(paramType));
|
||||||
|
}
|
||||||
|
injectedTypes.add(paramType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add any provided arguments for remaining parameters
|
||||||
|
var providedArgs = <dynamic>[];
|
||||||
|
if (arg1 != null) providedArgs.add(arg1);
|
||||||
|
|
||||||
|
// Process remaining parameters in order
|
||||||
|
var paramIndex = 0;
|
||||||
|
var providedIndex = 0;
|
||||||
|
for (var param in reflectedFunction.parameters) {
|
||||||
|
if (param.isNamed) continue;
|
||||||
|
if (injectedTypes.contains(param.type.reflectedType)) {
|
||||||
|
paramIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (providedIndex < providedArgs.length) {
|
||||||
|
resolvedArgs.add(providedArgs[providedIndex++]);
|
||||||
|
} else if (param.isRequired) {
|
||||||
|
throw BindingResolutionException(
|
||||||
|
'No value provided for required parameter ${param.name} of type ${param.type.reflectedType}');
|
||||||
|
}
|
||||||
|
paramIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function with resolved arguments
|
||||||
|
return Function.apply(callback, resolvedArgs, namedArgs);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Register a binding if it hasn't already been registered
|
/// Register a binding if it hasn't already been registered
|
||||||
void bindIf<T>(dynamic concrete, {bool singleton = false}) {
|
void bindIf<T>(dynamic concrete, {bool singleton = false}) {
|
||||||
if (!has<T>()) {
|
if (!has<T>()) {
|
||||||
|
@ -1181,6 +1248,19 @@ class Container {
|
||||||
bindIf<T>(concrete, singleton: true);
|
bindIf<T>(concrete, singleton: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a factory binding for deferred resolution
|
||||||
|
///
|
||||||
|
/// This method allows you to create a factory binding that will be resolved
|
||||||
|
/// only when the dependency is requested. This is useful for lazy loading
|
||||||
|
/// and circular dependency resolution.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// container.factory<Logger>(() => ConsoleLogger());
|
||||||
|
/// ```
|
||||||
|
void factory<T>(T Function() concrete) {
|
||||||
|
registerFactory<T>((container) => concrete());
|
||||||
|
}
|
||||||
|
|
||||||
/// Register all attribute-based bindings for a type
|
/// Register all attribute-based bindings for a type
|
||||||
void registerAttributeBindings(Type type) {
|
void registerAttributeBindings(Type type) {
|
||||||
var annotations = reflector.getAnnotations(type);
|
var annotations = reflector.getAnnotations(type);
|
||||||
|
|
209
incubation/container/container/test/factory_test.dart
Normal file
209
incubation/container/container/test/factory_test.dart
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
import 'package:platformed_container/container.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
abstract class Logger {
|
||||||
|
void log(String message);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConsoleLogger implements Logger {
|
||||||
|
@override
|
||||||
|
void log(String message) => print('Console: $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late Container container;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
container = Container(MockReflector());
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Factory Tests', () {
|
||||||
|
test('factory creates deferred binding', () {
|
||||||
|
var created = false;
|
||||||
|
container.factory<Logger>(() {
|
||||||
|
created = true;
|
||||||
|
return ConsoleLogger();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify binding is not created yet
|
||||||
|
expect(created, isFalse);
|
||||||
|
|
||||||
|
// Resolve the binding
|
||||||
|
var logger = container.make<Logger>();
|
||||||
|
|
||||||
|
// Verify binding was created
|
||||||
|
expect(created, isTrue);
|
||||||
|
expect(logger, isA<ConsoleLogger>());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('factory creates new instance each time', () {
|
||||||
|
container.factory<Logger>(() => ConsoleLogger());
|
||||||
|
|
||||||
|
var logger1 = container.make<Logger>();
|
||||||
|
var logger2 = container.make<Logger>();
|
||||||
|
|
||||||
|
expect(logger1, isNot(same(logger2)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('factory throws when already bound', () {
|
||||||
|
container.factory<Logger>(() => ConsoleLogger());
|
||||||
|
|
||||||
|
expect(() => container.factory<Logger>(() => ConsoleLogger()),
|
||||||
|
throwsA(isA<StateError>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('factory works with interfaces', () {
|
||||||
|
container.factory<Logger>(() => ConsoleLogger());
|
||||||
|
|
||||||
|
var logger = container.make<Logger>();
|
||||||
|
expect(logger, isA<Logger>());
|
||||||
|
expect(logger, isA<ConsoleLogger>());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('factory preserves parameter overrides', () {
|
||||||
|
var paramValue = '';
|
||||||
|
container.factory<Logger>(() {
|
||||||
|
paramValue = container.getParameterOverride('level') as String;
|
||||||
|
return ConsoleLogger();
|
||||||
|
});
|
||||||
|
|
||||||
|
container.withParameters({'level': 'debug'}, () {
|
||||||
|
container.make<Logger>();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(paramValue, equals('debug'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflector extends Reflector {
|
||||||
|
@override
|
||||||
|
String? getName(Symbol symbol) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClass? reflectClass(Type clazz) {
|
||||||
|
if (clazz == ConsoleLogger) {
|
||||||
|
return MockReflectedClass(
|
||||||
|
'ConsoleLogger', [], [], [MockConstructor('', [])], ConsoleLogger);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType? reflectType(Type type) {
|
||||||
|
return reflectClass(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance? reflectInstance(Object? instance) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunction? reflectFunction(Function function) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType reflectFutureOf(Type type) => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Type? findTypeByName(String name) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunction? findInstanceMethod(Object instance, String methodName) =>
|
||||||
|
null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> getAnnotations(Type type) => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> getParameterAnnotations(
|
||||||
|
Type type, String constructorName, String parameterName) =>
|
||||||
|
[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockConstructor implements ReflectedFunction {
|
||||||
|
final String constructorName;
|
||||||
|
final List<ReflectedParameter> constructorParameters;
|
||||||
|
|
||||||
|
MockConstructor(this.constructorName, this.constructorParameters);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> get annotations => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isGetter => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isSetter => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => constructorName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedParameter> get parameters => constructorParameters;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType? get returnType => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedTypeParameter> get typeParameters => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance invoke(Invocation invocation) => throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflectedClass extends ReflectedType implements ReflectedClass {
|
||||||
|
@override
|
||||||
|
final List<ReflectedInstance> annotations;
|
||||||
|
@override
|
||||||
|
final List<ReflectedFunction> constructors;
|
||||||
|
@override
|
||||||
|
final List<ReflectedDeclaration> declarations;
|
||||||
|
|
||||||
|
MockReflectedClass(
|
||||||
|
String name,
|
||||||
|
List<ReflectedTypeParameter> typeParameters,
|
||||||
|
this.annotations,
|
||||||
|
this.constructors,
|
||||||
|
Type reflectedType,
|
||||||
|
) : declarations = [],
|
||||||
|
super(reflectedType.toString(), typeParameters, reflectedType);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance newInstance(
|
||||||
|
String constructorName, List positionalArguments,
|
||||||
|
[Map<String, dynamic> namedArguments = const {},
|
||||||
|
List<Type> typeArguments = const []]) {
|
||||||
|
if (reflectedType == ConsoleLogger) {
|
||||||
|
return MockReflectedInstance(ConsoleLogger());
|
||||||
|
}
|
||||||
|
throw UnsupportedError('Unknown type: $reflectedType');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAssignableTo(ReflectedType? other) {
|
||||||
|
if (reflectedType == other?.reflectedType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (reflectedType == ConsoleLogger && other?.reflectedType == Logger) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflectedInstance implements ReflectedInstance {
|
||||||
|
final dynamic value;
|
||||||
|
|
||||||
|
MockReflectedInstance(this.value);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClass get clazz => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance getField(String name) => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
dynamic get reflectee => value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType get type => throw UnimplementedError();
|
||||||
|
}
|
306
incubation/container/container/test/wrap_test.dart
Normal file
306
incubation/container/container/test/wrap_test.dart
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
import 'package:platformed_container/container.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
abstract class Logger {
|
||||||
|
void log(String message);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConsoleLogger implements Logger {
|
||||||
|
@override
|
||||||
|
void log(String message) => print('Console: $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
late Container container;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
container = Container(MockReflector());
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Wrap Tests', () {
|
||||||
|
test('wrap injects dependencies into closure', () {
|
||||||
|
container.bind(Logger).to(ConsoleLogger);
|
||||||
|
var messages = <String>[];
|
||||||
|
|
||||||
|
var wrapped = container.wrap((Logger logger, String message) {
|
||||||
|
messages.add(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapped('Hello world'); // Pass message directly
|
||||||
|
expect(messages, contains('Hello world'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('wrap preserves provided arguments', () {
|
||||||
|
container.bind(Logger).to(ConsoleLogger);
|
||||||
|
var messages = <String>[];
|
||||||
|
|
||||||
|
var wrapped = container.wrap((Logger logger, String message) {
|
||||||
|
messages.add(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapped('Custom message'); // Pass message directly
|
||||||
|
expect(messages, contains('Custom message'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('wrap throws when required dependency is missing', () {
|
||||||
|
var wrapped = container.wrap((Logger logger) {});
|
||||||
|
|
||||||
|
expect(() => wrapped(), throwsA(isA<BindingResolutionException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('wrap works with optional parameters', () {
|
||||||
|
container.bind(Logger).to(ConsoleLogger);
|
||||||
|
var messages = <String>[];
|
||||||
|
|
||||||
|
var wrapped = container.wrap((Logger logger, [String? message]) {
|
||||||
|
messages.add(message ?? 'default');
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapped(); // No arguments needed
|
||||||
|
expect(messages, contains('default'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('wrap works with named parameters', () {
|
||||||
|
container.bind(Logger).to(ConsoleLogger);
|
||||||
|
var messages = <String>[];
|
||||||
|
|
||||||
|
var wrapped =
|
||||||
|
container.wrap((Logger logger, {String message = 'default'}) {
|
||||||
|
messages.add(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapped(); // No arguments needed
|
||||||
|
expect(messages, contains('default'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflector extends Reflector {
|
||||||
|
@override
|
||||||
|
String? getName(Symbol symbol) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClass? reflectClass(Type clazz) {
|
||||||
|
if (clazz == ConsoleLogger) {
|
||||||
|
return MockReflectedClass(
|
||||||
|
'ConsoleLogger', [], [], [MockConstructor('', [])], ConsoleLogger);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType? reflectType(Type type) {
|
||||||
|
return reflectClass(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance? reflectInstance(Object? instance) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunction? reflectFunction(Function function) {
|
||||||
|
// Create mock parameters based on the function's runtime type
|
||||||
|
var parameters = <ReflectedParameter>[];
|
||||||
|
|
||||||
|
// First parameter is always Logger
|
||||||
|
parameters.add(MockParameter('logger', Logger, true, false));
|
||||||
|
|
||||||
|
// Add message parameter based on function signature
|
||||||
|
if (function.toString().contains('String message')) {
|
||||||
|
parameters.add(MockParameter('message', String, true, false));
|
||||||
|
} else if (function.toString().contains('String? message')) {
|
||||||
|
parameters.add(MockParameter('message', String, false, false));
|
||||||
|
} else if (function.toString().contains('{String message')) {
|
||||||
|
parameters.add(MockParameter('message', String, false, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return MockFunction('', parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType reflectFutureOf(Type type) => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Type? findTypeByName(String name) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunction? findInstanceMethod(Object instance, String methodName) =>
|
||||||
|
null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> getAnnotations(Type type) => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> getParameterAnnotations(
|
||||||
|
Type type, String constructorName, String parameterName) =>
|
||||||
|
[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockConstructor implements ReflectedFunction {
|
||||||
|
final String constructorName;
|
||||||
|
final List<ReflectedParameter> constructorParameters;
|
||||||
|
|
||||||
|
MockConstructor(this.constructorName, this.constructorParameters);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> get annotations => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isGetter => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isSetter => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => constructorName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedParameter> get parameters => constructorParameters;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType? get returnType => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedTypeParameter> get typeParameters => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance invoke(Invocation invocation) => throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflectedClass extends ReflectedType implements ReflectedClass {
|
||||||
|
@override
|
||||||
|
final List<ReflectedInstance> annotations;
|
||||||
|
@override
|
||||||
|
final List<ReflectedFunction> constructors;
|
||||||
|
@override
|
||||||
|
final List<ReflectedDeclaration> declarations;
|
||||||
|
|
||||||
|
MockReflectedClass(
|
||||||
|
String name,
|
||||||
|
List<ReflectedTypeParameter> typeParameters,
|
||||||
|
this.annotations,
|
||||||
|
this.constructors,
|
||||||
|
Type reflectedType,
|
||||||
|
) : declarations = [],
|
||||||
|
super(reflectedType.toString(), typeParameters, reflectedType);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance newInstance(
|
||||||
|
String constructorName, List positionalArguments,
|
||||||
|
[Map<String, dynamic> namedArguments = const {},
|
||||||
|
List<Type> typeArguments = const []]) {
|
||||||
|
if (reflectedType == ConsoleLogger) {
|
||||||
|
return MockReflectedInstance(ConsoleLogger());
|
||||||
|
}
|
||||||
|
throw UnsupportedError('Unknown type: $reflectedType');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAssignableTo(ReflectedType? other) {
|
||||||
|
if (reflectedType == other?.reflectedType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (reflectedType == ConsoleLogger && other?.reflectedType == Logger) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockFunction implements ReflectedFunction {
|
||||||
|
final String functionName;
|
||||||
|
final List<ReflectedParameter> functionParameters;
|
||||||
|
|
||||||
|
MockFunction(this.functionName, this.functionParameters);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> get annotations => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isGetter => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isSetter => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => functionName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedParameter> get parameters => functionParameters;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType? get returnType => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedTypeParameter> get typeParameters => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance invoke(Invocation invocation) => throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockParameter implements ReflectedParameter {
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final bool isRequired;
|
||||||
|
@override
|
||||||
|
final bool isNamed;
|
||||||
|
final Type paramType;
|
||||||
|
final bool isVariadic;
|
||||||
|
|
||||||
|
MockParameter(this.name, this.paramType, this.isRequired, this.isNamed,
|
||||||
|
{this.isVariadic = false});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedInstance> get annotations => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType get type => MockReflectedType(paramType);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflectedType implements ReflectedType {
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final Type reflectedType;
|
||||||
|
|
||||||
|
MockReflectedType(this.reflectedType) : name = reflectedType.toString();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ReflectedTypeParameter> get typeParameters => [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAssignableTo(ReflectedType? other) {
|
||||||
|
if (reflectedType == other?.reflectedType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (reflectedType == ConsoleLogger && other?.reflectedType == Logger) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance newInstance(
|
||||||
|
String constructorName, List positionalArguments,
|
||||||
|
[Map<String, dynamic> namedArguments = const {},
|
||||||
|
List<Type> typeArguments = const []]) =>
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockReflectedInstance implements ReflectedInstance {
|
||||||
|
final dynamic value;
|
||||||
|
|
||||||
|
MockReflectedInstance(this.value);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClass get clazz => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstance getField(String name) => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
dynamic get reflectee => value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedType get type => throw UnimplementedError();
|
||||||
|
}
|
Loading…
Reference in a new issue