【问题标题】:Instantiate a class from a string从字符串实例化一个类
【发布时间】:2012-12-23 22:37:19
【问题描述】:

在 dart 中是否可以从字符串实例化一个类?

例如:

  • javascript 中的香草:
var myObject = window[classNameString];
  • 目标-C:
id myclass = [[NSClassFromString(@"MyClass") alloc] init];

【问题讨论】:

    标签: dart dart-mirrors


    【解决方案1】:

    您需要知道库名和类名才能正常工作。假设你都知道,下面的例子将实例化 TestClass 并在其上调用 doStuff

    library test;
    
    import "dart:mirrors";
    
    class TestClass {
      doStuff() => print("doStuff was called!");
    }
    
    main() {
      MirrorSystem mirrors = currentMirrorSystem();
      LibraryMirror lm = mirrors.libraries['test'];
      ClassMirror cm = lm.classes['TestClass'];
      Future tcFuture = cm.newInstance('', []);
      tcFuture.then((InstanceMirror im) {
        var tc = im.reflectee;
        tc.doStuff();
      });
    }
    

    关于此解决方案的几点说明:

    1. 我们尝试从中加载类的库 test 已经导入到 VM 中,这使得这种情况更容易一些。
    2. newInstance 的调用允许将参数传递给构造函数。位置参数已实现,但命名参数尚未实现(从 M2 版本开始)。
    3. newInstance 返回一个 Future 以允许它跨 isolates 工作。

    【讨论】:

    • newInstance 不返回 Future 因为实例化类可能需要异步操作,这不是真的,一切都已经加载。它返回一个Future,因为 Mirrors API 是有意异步的,因为它将在未来跨隔离区工作(并且跨隔离区通信始终是异步的)。如果您仔细检查 newInstance 调用(以及其他类似 get/setFieldinvoke 的调用),您会注意到它在后台是同步工作的。这在未来可能会明显改变。
    • 注意:编译成 JavaScript 时这可能不起作用。 dart2js 编译器还不完全支持镜像。
    • 呃 .. 这让 Dart 看起来不像 Java 那样动态 .. 反射是一个非常重要的特性 ..
    【解决方案2】:

    语法已更改。 我是这样弄的

    library test;
    
    import "dart:mirrors";
    
    class TestClass {
      doStuff() => print("doStuff was called!");
    }
    
    main() {
      MirrorSystem mirrors = currentMirrorSystem();
      LibraryMirror lm = mirrors.libraries.values.firstWhere(
          (LibraryMirror lm) => lm.qualifiedName == new Symbol('test'));
    
      ClassMirror cm = lm.declarations[new Symbol('TestClass')];
    
      InstanceMirror im = cm.newInstance(new Symbol(''), []);
      var tc = im.reflectee;
      tc.doStuff();
    }
    

    如果有更多名为 'test' 的库,这将失败。

    【讨论】:

    • 确实,classes getter 已更改为 declarations
    【解决方案3】:

    这个问题一直困扰着我,直到我发现我可以实现一个粗略的 from 方法来处理 编码的 Json 对象/字符串 的转换飞镖映射到所需的类。

    下面是一个简单的例子,它也处理空值并接受 JSON(作为 字符串 参数

    import 'dart:convert';
    
    class PaymentDetail
    {
      String AccountNumber;
      double Amount;
      int ChargeTypeID;
      String CustomerNames;
    
      PaymentDetail({
        this.AccountNumber,
        this.Amount,
        this.ChargeTypeID,
        this.CustomerNames
      });
    
      PaymentDetail from ({ string : String, object : Map  }) {
         var map   = (object==null) ? (string==null) ? Map() : json.decode(string) : (object==null) ? Map() : object;
         return new PaymentDetail(
            AccountNumber             : map["AccountNumber"] as String,
            Amount                    : map["Amount"] as double,
            ChargeTypeID              : map["ChargeTypeID"] as int,
            CustomerNames             : map["CustomerNames"] as String
         );
      }
    
    }
    

    下面是它的实现

     PaymentDetail payDetail =  new PaymentDetail().from(object: new Map());
    
     PaymentDetail otherPayDetail =  new PaymentDetail().from(object: {"AccountNumber": "1234", "Amount": 567.2980908});
    

    再一次,这在整个项目中进行克隆既简单又乏味,但它适用于简单的情况。

    【讨论】:

      【解决方案4】:

      试试:

      Map models = {"Player": Player.instatiate};
      var player = models["Player"]();
      
      class Player{
        static instatiate() => Player();
      }
      

      【讨论】:

        猜你喜欢
        • 2020-12-15
        • 1970-01-01
        • 1970-01-01
        • 2011-10-19
        • 1970-01-01
        • 2018-08-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多