如何在 Flex 3 中动态实例化类并在运行时设置属性?

发布于 2024-08-21 21:54:15 字数 2399 浏览 4 评论 0原文

使用 org.as3commons.reflect 我可以查找类名,并在运行时实例化一个类。我还有调用方法的(非工作)代码。但是,我真的想设置一个属性值。我不确定属性是否在 Flex 内部作为方法实现。

我有一个元数据类,它存储 3 条信息:名称、值和类型(都是字符串)。我希望能够循环元数据对象数组并在实例化的类上设置相应的属性。


package com.acme.reporting.builders
{
 import com.acme.reporting.model.Metadata;

 import mx.core.UIComponent;

 import org.as3commons.reflect.ClassUtils;
 import org.as3commons.reflect.MethodInvoker;

 public class UIComponentBuilder implements IUIComponentBuilder
 {
  public function build(metadata:Array):UIComponent
  {
   var typeClass:Class = ClassUtils.forName(getTypeName(metadata));
   var result:* = ClassUtils.newInstance(typeClass);

   for each (var m:Metadata in metadata)
   {
    if (m.name == "type")
     continue;

    // Attempting to invoke as method,
                // would really like the property though

    var methodInvoker:MethodInvoker = new MethodInvoker();

    methodInvoker.target = result;
    methodInvoker.method = m.name;
    methodInvoker.arguments = [m.value];

    var returnValue:* = methodInvoker.invoke(); // Fails!
   }

   return result;
  }

  private static function getTypeName(metadata:Array):String
  {
   if (metadata == null || metadata.length == 0)
    throw new ArgumentError("metadata is null or empty");

   var typeName:String;

   // Type is usually the first entry
   if (metadata.length > 1 && metadata[0] != null && metadata[0].name == "type")
   {
    typeName = metadata[0].value;
   }
   else
   {
    var typeMetadata:Array = metadata.filter(
     function(element:*, index:int, arr:Array):Boolean
     {
      return element.name == "type";
     }
    );

    if (typeMetadata == null || typeMetadata.length != 1)
     throw new ArgumentError("type entry not found in metadata");

    typeName = typeMetadata[0].value;
   }

   if (typeName == null || typeName.length == 0)
    throw new Error("typeName is null or blank");

   return typeName;
  }
 }
}

这是一些使用代码:


var metadata:Array = new Array();

metadata[0] = new Metadata("type", "mx.controls.Text", null);
metadata[1] = new Metadata("text", "Hello World!", null);
metadata[2] = new Metadata("x", "77", null);
metadata[3] = new Metadata("y", "593", null);

this.addChild(new UIComponentBuilder().build(metadata));

我意识到我必须声明要实例化的类型的虚拟变量,或者使用 -inculde 编译器指令。 Flex 的一个不幸的缺点。

另外,现在有代码可以将值类型转换为其指定类型。

Using org.as3commons.reflect I can look-up the class name, and instantiate a class at runtime. I also have (non-working) code which invokes a method. However, I really want to set a property value. I'm not sure if properties are realized as methods internally in Flex.

I have a Metadata class which stores 3 pieces of information: name, value, and type (all are strings). I want to be able to loop through an Array of Metadata objects and set the corresponding properties on the instantiated class.


package com.acme.reporting.builders
{
 import com.acme.reporting.model.Metadata;

 import mx.core.UIComponent;

 import org.as3commons.reflect.ClassUtils;
 import org.as3commons.reflect.MethodInvoker;

 public class UIComponentBuilder implements IUIComponentBuilder
 {
  public function build(metadata:Array):UIComponent
  {
   var typeClass:Class = ClassUtils.forName(getTypeName(metadata));
   var result:* = ClassUtils.newInstance(typeClass);

   for each (var m:Metadata in metadata)
   {
    if (m.name == "type")
     continue;

    // Attempting to invoke as method,
                // would really like the property though

    var methodInvoker:MethodInvoker = new MethodInvoker();

    methodInvoker.target = result;
    methodInvoker.method = m.name;
    methodInvoker.arguments = [m.value];

    var returnValue:* = methodInvoker.invoke(); // Fails!
   }

   return result;
  }

  private static function getTypeName(metadata:Array):String
  {
   if (metadata == null || metadata.length == 0)
    throw new ArgumentError("metadata is null or empty");

   var typeName:String;

   // Type is usually the first entry
   if (metadata.length > 1 && metadata[0] != null && metadata[0].name == "type")
   {
    typeName = metadata[0].value;
   }
   else
   {
    var typeMetadata:Array = metadata.filter(
     function(element:*, index:int, arr:Array):Boolean
     {
      return element.name == "type";
     }
    );

    if (typeMetadata == null || typeMetadata.length != 1)
     throw new ArgumentError("type entry not found in metadata");

    typeName = typeMetadata[0].value;
   }

   if (typeName == null || typeName.length == 0)
    throw new Error("typeName is null or blank");

   return typeName;
  }
 }
}

Here's some usage code:


var metadata:Array = new Array();

metadata[0] = new Metadata("type", "mx.controls.Text", null);
metadata[1] = new Metadata("text", "Hello World!", null);
metadata[2] = new Metadata("x", "77", null);
metadata[3] = new Metadata("y", "593", null);

this.addChild(new UIComponentBuilder().build(metadata));

I realize that I have to declare a dummy variable of the type I was to instantiate, or use the -inculde compiler directive. An unfortunate drawback of Flex.

Also, right now there's code to account for typecasting the value to it's specified type.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心碎的声音 2024-08-28 21:54:15

AS3 中的动态执行比其他语言简单得多。这段代码:

var methodInvoker:MethodInvoker = new MethodInvoker();

methodInvoker.target = result;
methodInvoker.method = m.name;
methodInvoker.arguments = [m.value];

var returnValue:* = methodInvoker.invoke(); // Fails!

可以简化为:

var returnValue:* = result[method](m.value);

编辑

因为它是一个属性,所以会像这样完成:

result[method] = m.value;

并且没有返回值(好吧,你可以再次调用 getter,但它应该只返回m.value 除非 setter/getter 做了一些奇怪的事情。

Dynamic execution in AS3 is much simpler than in other languages. This code:

var methodInvoker:MethodInvoker = new MethodInvoker();

methodInvoker.target = result;
methodInvoker.method = m.name;
methodInvoker.arguments = [m.value];

var returnValue:* = methodInvoker.invoke(); // Fails!

can be simplified to this:

var returnValue:* = result[method](m.value);

EDIT:

Since it's a property, it would be done like this:

result[method] = m.value;

and there is no return value (well, you can call the getter again but it should just return m.value unless the setter/getter do something funky.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文