如何使用dart实现委托/代理?

Fre*_*ind 4 proxy delegates nosuchmethod dart dart-mirrors

我有两个类ParserProxy,当我从调用的方法Parser,它不存在,它会委托给Proxy类.

我的代码:

class Parser {
    noSuchMethod(Invocation invocation) {
        // how to pass the `invocation` to `Proxy`???
    }
}

class Proxy {
    static String hello() { return "hello"; }
    static String world() { return "world"; }
}
Run Code Online (Sandbox Code Playgroud)

我写的时候:

var parser = new Parser();
print(parser.hello());
Run Code Online (Sandbox Code Playgroud)

它将打印:

hello
Run Code Online (Sandbox Code Playgroud)

Ale*_*uin 7

你必须使用dart:mirrors.这是怎么做的:

import 'dart:mirrors';

class Parser {
  noSuchMethod(Invocation invocation) {
    ClassMirror cm = reflectClass(Proxy);
    return cm.invoke(invocation.memberName
        , invocation.positionalArguments
        /*, invocation.namedArguments*/ // not implemented yet
        ).reflectee;
  }
}

class Proxy {
  static String hello() { return "hello"; }
  static String world() { return "world"; }
}

main(){
  var parser = new Parser();
  print(parser.hello());
  print(parser.world());
}
Run Code Online (Sandbox Code Playgroud)


Sha*_*uli 6

亚历山大的回答是正确的,但我想补充一点。

我假设委托Proxy是一个实现细节,我们不希望用户接触到它。在这种情况下,我们应该对调用parser不支持的方法的情况进行一些处理Proxy。现在,如果你这样做:

void main() {
  var parser = new Parser();
  print(parser.foo());
}
Run Code Online (Sandbox Code Playgroud)

您收到此错误:

Unhandled exception:
Compile-time error during mirrored execution: <Dart_Invoke: did not find static method 'Proxy.foo'.>
Run Code Online (Sandbox Code Playgroud)

我会noSuchMethod以稍微不同的方式编写代码。在委托给 之前Proxy,我会检查是否Proxy支持我将要调用的方法。如果Proxy支持它,我会Proxy像 Alexandre 在他的回答中描述的那样调用该方法。如果Proxy不支持该方法,我会抛出一个NoSuchMethodError.

这是答案的修订版:

import 'dart:mirrors';

class Parser {
  noSuchMethod(Invocation invocation) {
    ClassMirror cm = reflectClass(Proxy);
    if (cm.methods.keys.contains(invocation.memberName)) {
      return cm.invoke(invocation.memberName
          , invocation.positionalArguments
          /*, invocation.namedArguments*/ // not implemented yet
          ).reflectee;
    }
    throw new NoSuchMethodError(this,
        _symbolToString(invocation.memberName),
        invocation.positionalArguments,
        _symbolMapToStringMap(invocation.namedArguments));
  }
}


String _symbolToString(Symbol symbol) => MirrorSystem.getName(symbol);

Map<String, dynamic> _symbolMapToStringMap(Map<Symbol, dynamic> map) {
  if (map == null) return null;
  var result = new Map<String, dynamic>();
  map.forEach((Symbol key, value) {
    result[_symbolToString(key)] = value;
  });
  return result;
}

class Proxy {
  static String hello() { return "hello"; }
  static String world() { return "world"; }
}

main(){
  var parser = new Parser();
  print(parser.hello());
  print(parser.world());
  print(parser.foo());
}
Run Code Online (Sandbox Code Playgroud)

这是运行此代码的输出:

hello
world
Unhandled exception:
NoSuchMethodError : method not found: 'foo'
Receiver: Instance of 'Parser'
Arguments: []
Run Code Online (Sandbox Code Playgroud)