context.dart 1.75 KB
Newer Older
1 2 3 4 5 6
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

7
final AppContext _defaultContext = new AppContext();
8

9 10
typedef void ErrorHandler(dynamic error);

11 12 13 14 15 16 17
/// A singleton for application functionality. This singleton can be different
/// on a per-Zone basis.
AppContext get context {
  AppContext currentContext = Zone.current['context'];
  return currentContext == null ? _defaultContext : currentContext;
}

18 19
class AppContext {
  Map<Type, dynamic> _instances = <Type, dynamic>{};
20

21 22 23 24 25 26 27 28
  bool isSet(Type type) {
    if (_instances.containsKey(type))
      return true;

    AppContext parent = _calcParent(Zone.current);
    return parent != null ? parent.isSet(type) : false;
  }

29 30 31
  dynamic getVariable(Type type) {
    if (_instances.containsKey(type))
      return _instances[type];
32

33 34 35
    AppContext parent = _calcParent(Zone.current);
    return parent?.getVariable(type);
  }
36

37 38 39
  void setVariable(Type type, dynamic instance) {
    _instances[type] = instance;
  }
40

41
  dynamic operator[](Type type) => getVariable(type);
42

43
  void operator[]=(Type type, dynamic instance) => setVariable(type, instance);
44

45 46 47
  AppContext _calcParent(Zone zone) {
    if (this == _defaultContext)
      return null;
48

49 50 51
    Zone parentZone = zone.parent;
    if (parentZone == null)
      return _defaultContext;
52

53 54 55 56 57 58
    AppContext deps = parentZone['context'];
    if (deps == this) {
      return _calcParent(parentZone);
    } else {
      return deps != null ? deps : _defaultContext;
    }
59 60
  }

61 62 63 64 65 66
  dynamic runInZone(dynamic method(), { ErrorHandler onError }) {
    return runZoned(
      method,
      zoneValues: <String, dynamic>{ 'context': this },
      onError: onError
    );
67 68
  }
}