construct method

void construct(
  1. ValueResolver valueResolver
)

Creates the target, an instance of targetType, by calling its constructor with values from valueResolver: constructor binding, for classes with final fields. Spring's DataBinder.construct.

Each constructor parameter is looked up by name (isbn), a nested @Introspected object by prefix (author.name), lists and sets by index (tags[0], authors[1].name) and maps by key (prices[eur]). Values are converted to the parameter types, and optional parameters without a value keep their defaults.

A value that cannot be converted, or no value for a required non-nullable parameter (Java's missing primitive), records a typeMismatch error; target then stays null when the object cannot be created. Without errors the binding result starts afresh for the new target, so bind and validate can follow.

Throws a StateError when there is already a target or targetType is not set, an ArgumentError when targetType is not @Introspected, and an InvalidPropertyException for a list index at or above autoGrowCollectionLimit, before the list is allocated (Spring's createList).

// A Book with final fields, created from form input.
final binder =
    DataBinder(null, objectName: 'book', introspector: introspector)
  ..targetType = Book
  ..construct(MapValueResolver({'isbn': '978-0', 'title': 'Dune'}));
binder.bindingResult.hasErrors; // false

Implementation

void construct(ValueResolver valueResolver) {
  if (_target != null) {
    throw StateError('Target instance already available');
  }
  final type = targetType ?? (throw StateError('Target type not set'));
  final introspection =
      introspector.forType(type) ??
      (throw ArgumentError.value(
        type,
        'targetType',
        '$type is not @Introspected (or its module is not registered)',
      ));
  _target = _createObject(introspection, '', valueResolver);
  if (_target != null && !bindingResult.hasErrors) {
    _bindingResult = null;
  }
}