【问题标题】:Loading classes dynamically in Dart在 Dart 中动态加载类
【发布时间】:2013-02-05 10:04:26
【问题描述】:

所以,我查看了镜子,它们可能是一种选择,但考虑到它们的异步特性,它们可能真的很难使用,或者从长远来看是不可行的。由于它们目前不受支持(只是一个玩物),因此无论如何它们目前都不可行。

问题:给定一系列字符串,例如。 [ "Foo", "Bar" ]library corelib; 中的基类ApplicationWidget 以及library applibrary; 中每个字符串FooWidgetBarWidget 的对应类,目前最优雅的获取Application 的方法是将字符串转换为相应类的实例,适用于 dart2js

为了清楚起见,等效的 PHP 伪示例,

<?php # example

namespace corelib;

class Widget {
    function name() { 
        return \get_called_class(); 
    }
}

class Application {
    static function resolve($name, $library) { 
        $class = $library.'\\'.$name.'Widget'; 
        return new $class;
    }
}

namespace applibrary;

class FooWidget extends \corelib\Widget {
    // ...
}

class BarWidget extends \corelib\Widget {
    // ...
}

$foowidget = \corelib\Application::resolve('Foo', 'applibrary');
$barwidget = \corelib\Application::resolve('Bar', 'applibrary');

echo "{$foowidget->name()} <br> {$barwidget->name()}";

输出

applibrary\FooWidget 
applibrary\BarWidget

【问题讨论】:

    标签: dart dart-mirrors


    【解决方案1】:

    如果您可以验证字符串列表,那么目前最好的方法(直到 dart2js 中的镜像支持变得更好)可能是 if 语句。

    // toy implementation
    Widget getWidget(name) {
      switch (name) {
         case "Foo": return new FooWidget();
         case "Bar": return new FooWidget();
         default: // handle error
      } 
    } 
    
    // elsewhere:
    var fooWidget = getWidget("Foo");
    var barWidget = getWidget("Bar");
    

    xyzWidget 类的列表将是一个有限列表(因为无论如何您都无法在运行时动态链接代码)。

    当然,更优雅的实现是使用镜像(如下所示,供参考,虽然它目前不满足 dar2js 标准)

    Future<Widget> getWidget(library, name) {
      var completer = new Completer<Widget>();
      MirrorSystem ms = currentMirrorSystem();
      ClassMirror cm = ms.libraries[library].classes[name];
      // instantiate an instance of the class
      cm.newInstance(null,[]).then((instance) => completer.complete(instance));
    
      return completer.future;
    }
    
    // elsewhere:   
    getWidget("applibrary","FooWidget").then((Widget widget) {
      // do something with widget
    });
    

    【讨论】:

    • 担心这可能是唯一的方法。我目前实际上正在使用类似的解决方案(作为权宜之计),只是我将Map&lt;String, widgetresolver&gt;传递给核心库中的Environment类并让它执行widgetresolver而不是开关/功能(这是一个简单的函数typedef) 每次给我一个实例。在镜子的例子中,有没有办法让未来同步?整个未来对我没有任何帮助,因为我必须让应用程序等待所有小部件才能相互执行交叉计算。
    • 我喜欢你的小部件解析器解决方案。这比 switch 语句更优雅:)。关于让应用程序等待,无论如何你肯定需要这样做:FooWidget 和 BarWidget 都需要实例化,然后才能对彼此进行计算。
    • 好吧,因为我只是在实例化一个类,所以我不觉得浪费时间思考期货(在整个应用程序中)有任何价值。我想要的只是一个正确类的简单实例;如果我必须在实例化它之后手动初始化它,那很好。一种在 Widget 类上创建工厂的方法,它直接向我传递一个实例,类似于我描述我现在从 Environment 类中获取一个实例的方式,这将避免很多潜在的复杂逻辑;这很有趣,因为我希望示例中的伪 corelib 是可重用的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 2014-11-16
    • 2011-07-31
    相关资源
    最近更新 更多