从外部对象分配属性

时间:2019-10-21 20:08:24

标签: flutter dart

我正在尝试从外部对象设置属性:

main() {
  A a = A();
  print(a.prop.runtimeType); // is 'Null'
  MiddleMan().b.assign(a.prop);
  print(a.prop.runtimeType); // should be 'B', but is 'Null'
}

class A { B prop; }

class MiddleMan { B b = B(); }

class B {
  assign(B property) { property = this; }
}

我设法通过镜子实现了此功能:

import 'dart:mirrors';

main() {
  A a = A();
  print(a.prop.runtimeType); // is 'Null'
  MiddleMan().b.assign(a, 'prop');
  print(a.prop.runtimeType); // is 'B'
}

class A { B prop; }

class MiddleMan { B b = B(); }

class B {
  assign(dynamic object, String property) {
    InstanceMirror reflectee = reflect(object);
    reflectee.setField(Symbol(property), this);
  }
}

但是后来我意识到在Flutter中禁用了镜像。有什么解决方法吗?

1 个答案:

答案 0 :(得分:0)

正如here所述,可以使用包装器类:

main() {
  A a = new A();
  print(a.prop.value.runtimeType); // is 'Null'
  MiddleMan().b.assign(a.prop);
  print(a.prop.value.runtimeType); // is 'B'
}

class A {
  Wrapper<B> prop = Wrapper(null);
}

class MiddleMan {
  B b = B();
}

class B {
  assign(Wrapper<B> property) {
    property.value = this;
  }
}

class Wrapper<T> {
  T value;

  Wrapper(this.value);
}

但是因为我的意图是编写一个库并使用户易于使用,所以只需一行调用即可:

MiddleMan().b.assign(a.prop);

同时,在分配属性时,我需要可选地处理其他内容,因此,像a.prop = MiddleMan().b;这样的直接分配,现在我决定在重载&运算符时使用某种不寻常的语法,其用法如下:

a.prop = MiddleMan().b;

或可选:

a.prop = MiddleMan().b & doAdditionalStuff;

这是实现:

class B {
  B operator &(Function doAdditionalStuff) {
    if (doAdditionalStuff != null)
      doAdditionalStuff();

    return this;
  }
}

为了更清楚地了解我要实现的目标,我的lib应该与Provider库一起使用。用户代码示例:

class MyStore with ChangeNotifier {
  B prop;

  MyStore() {
    // MiddleMan is Singleton
    prop = MiddleMan().b;
    // or alternatively
    prop = MiddleMan().b & notifyListeners;
  }
}

库代码示例:

class B {
  List<Function> _reactives = [];

  B operator &(Function notifyListenersCallback) {
    if (notifyListenersCallback != null)
      this._reactives.add(notifyListenersCallback);

    return this;
  }

  // called on each internally triggered change
  notifyListeners() {
    for (Function reactive in this._reactives) {
      if (reactive != null)
        reactive();
    }
  }
}