`
qzriso
  • 浏览: 242983 次
  • 性别: Icon_minigender_1
  • 来自: ph
社区版块
存档分类
最新评论

利用XML动态创建类

阅读更多

这是一个很好用的技术,我已经在As3中使用它好长一段时间了。使用之前最基本的条件是,你已经知道了类的名字和所属包的的路径,这样就可以轻而易举的在运行时创建类。那么为什么需要这么做呢?有两种情况:一是你有从外部的swf导入的类,二是你已经编译了所有的类,却还想按照XML的配置改变其中的一些类,又不想重新编译。当你用一种CMS生成了你的站点,那么这也是一个非常好用的技术。想象一下,可以把类用于CMS的一段中(a section in the CMS),并且允许编辑从一套“类模板”中选取所需要的。现在,我们有一些在某些地方使用的例子,一起看看我们是如何轻松实现它的。

第一步:创建一个测试类

第一件事情,我们需要做的是创建一个测试类。在你的项目中,创建一个包路径为com.flashartofwar.example的类,如下所示:

  1. package com.flashartofwar.example {
  2.          import flash.display.Sprite;
  3.          /**
  4.           * @author jessefreeman
  5.           */
  6.          public class RedBox extends Sprite {
  7.                   
  8.                   protected var _width:Number = 0;
  9.                   protected var _height:Number = 0;
  10.                   
  11.                   /**
  12.                    * We override the public setter for width so we can redraw
  13.                    * the box when the width is changed.
  14.                    */
  15.                   override public function set width(value : Number) : void {
  16.                            _width = value;
  17.                            trace("Width", super.width);
  18.                            redraw();
  19.                    }
  20.   
  21.                   override public function get width() : Number {
  22.                            return _width;
  23.                    }
  24.   
  25.                   /**
  26.                    * We override the public setter for width so we can redraw
  27.                    * the box when the width is changed.
  28.                    */
  29.                   override public function set height(value : Number) : void {
  30.                            _height = value;
  31.                            redraw();
  32.                    }
  33.   
  34.                   override public function get height() : Number {
  35.                            return _height;
  36.                    }
  37.   
  38.                   public function RedBox() {
  39.                            width = 100;
  40.                            height = 100;
  41.                            redraw();
  42.                    }
  43.                   
  44.                   /**
  45.                    * This simply clears the graphics and redraws the box based
  46.                    * on the new width and height.
  47.                    */               
  48.                   public function redraw():void
  49.                   {
  50.                            graphics.clear();
  51.                            graphics.beginFill(0xFF0000);
  52.                            graphics.drawRect(0, 0, width, height);
  53.                            graphics.endFill();
  54.                    }
  55.           }
  56. }
复制代码

就像你看到的,这个基本的类继承了Sprite,并添加了管理width/height的自定义逻辑,还画了一个shape。我不愿将更多的时间花费在这个类上,它只是一个最基本的例子,任何的类都可以在这里良好的运行。

第2步:建立一个Doc类

现在我们需要一个文档类,来测试我们的RedBox类是否工作。

  1. package {
  2.          import flash.display.StageAlign;
  3.          import flash.display.StageScaleMode;
  4.          import com.flashartofwar.example.RedBox;
  5.          import flash.display.Sprite;
  6.          /**
  7.           * @author jessefreeman
  8.           */
  9.          public class DynamicClassDemo extends Sprite {
  10.                   public function DynamicClassDemo() {
  11.                            configureStage();
  12.                            createRedBox();
  13.                    }
  14.                   
  15.                   private function configureStage() : void {
  16.                            stage.scaleMode = StageScaleMode.NO_SCALE;
  17.                            stage.align = StageAlign.TOP_LEFT;
  18.                    }
  19.   
  20.                   private function createRedBox() : void {
  21.                            var redBox:RedBox = new RedBox();
  22.                            redBox.width = 100;
  23.                            redBox.height = 100;
  24.                            redBox.x = redBox.y = 10;
  25.                            addChild(redBox);
  26.                    }
  27.           }
  28. }
复制代码

同样,这个类也没什么特殊的。我设定了下stage,并建立一个可以创建RedBox的类。如果你运行下,你会看到一个100×100的红色的盒子。到这为止呢,所有的事情看起来都是这么的正确。

第三步:使用getDefinitionByName
接下来,让我们尝试下动态创建RedBox类。我将要使用到一个叫做getDefinitionByName的包方法,它可以通过完整的包路径和类名来查找某个类。把createRedBox方法用以下的代码替换。

  1. private function createRedBox() : void {
  2.          var tempClass : Class = getDefinitionByName("com.flashartofwar.example.RedBox") as Class;
  3.          
  4.          var redBox:RedBox = new tempClass();
  5.          redBox.width = 100;
  6.          redBox.height = 100;
  7.          redBox.x = redBox.y = 10;
  8.          addChild(redBox);
  9. }
复制代码

你也要导入如下:

  1. import flash.utils.getDefinitionByName;
复制代码

好,注意到了吗?我们这里只是简单地用new tempClass()替换了new RedBox(),并在这行之前使用了getDefinitionByName方法。只有这一点改变。我们建立了一个Class类型的持有变量,然后用getDefinitionByName返回了一个com.flashartofwar.example.RedBox类的实例。一旦我们有了一个类自己的引用,那么我们就可以简单地创建新的实例。灵巧的技巧,对吧?同样,我们若不使用As3自己的internal类去到系统里找我们所需要的类,这样写也是可以的,var tempClass:Class =com.flashartofwar.example.RedBox。运行一下,你同样可以看到一个和第2步相同的红色的盒子。
让我们通过XML来创建类吧,你可能会惊讶它有多么简单哦!

第四步:通过XML创建RedBox
现在我们要做与第三步同样的事情,只不过要把类的名字放到XML里。在这里例子里我要做些令人兴奋的

小变化。为什么你不用下面的代码再一次代替createRedBox呢?

  1.          // This is some sample XML data, we can just as easily
  2.          // loda this at runtime instead of compiling it in.
  3.          var xmlData:XML = <boxes base-package="com.flashartofwar.example">
  4.                  <box name="box1" class="RedBox" x="10" y="10" width="100" height="100"/>
  5.                  <box name="box2" class="RedBox" x="120" y="10" width="50" height="100"/>
  6.                  <box name="box3" class="RedBox" x="190" y="10" width="20" height="100"/>
  7.          </boxes>;
  8.          
  9.          // Pull out some core data we need from the xml
  10.          var basePackage:String = xmlData.@["base-package"];
  11.          var boxes:XMLList = xmlData.*;
  12.          var box:XML;
  13.          var boxInstance:DisplayObject;
  14.          
  15.          // Loop through each box node and build it's class
  16.          for each(box in boxes)
  17.          {
  18.                   // It is very important that we use quotes for the class
  19.                   // because it is a reserved word
  20.                   var tempClass : Class = getDefinitionByName(basePackage+"."+box.@["class"]) as Class;        
  21.                   // Here we type box to DisplayObject since we are not
  22.                   // sure what class it actually is
  23.                   boxInstance = new tempClass();
  24.                   boxInstance.x = Number(box.@x);
  25.                   boxInstance.y = Number(box.@y);
  26.                   boxInstance.width = Number(box.@width);
  27.                   boxInstance.height = Number(box.@height);
  28.                   
  29.                   addChild(boxInstance);
  30.           }
  31. }
复制代码

确定你要导入了下面的代码哦:

  1. import flash.display.DisplayObject;
复制代码

这回,我们有很多事情要做了,我添加了一些注释来帮助你。在上面的代码中,我们写了一些xml,并循环每一个box结点。一个好的技巧是,为了减少重复性得写代码,把package名字作为根结点的属性。下一步,你会看到每一个box都有一个名字、一个类、一个x值、一个y值,宽度和高度。最后的事情是,你应该注意我把redBox变量改成boxInstance,并且它现在的类型是DisplayObject类型的。运行下,看看发生了什么。

哦!你会看见如下的错误:

  1. ReferenceError: Error #1065: Variable RedBox is not defined.
  2.         at global/flash.utils::getDefinitionByName()
  3.         at DynamicClassDemo/createRedBox()
  4.         at DynamicClassDemo()
复制代码

在没有定义类型之前,它不再是com.flashartofwar.example.RedBox的引用,所以编译器会忽略导入它。这是在通过XML动态创建class的时候经常出的一个问题,我们不得不要使用一些技巧强制编译器包括这个类。让我们在com.flashartofwar.example包中创建一个叫做IncludeClasses 的新类:

  1. package com.flashartofwar.example {
  2.          /**
  3.           * @author jessefreeman
  4.           */
  5.          public class IncludeClasses {
  6.                   RedBox;
  7.           }
  8. }
复制代码

我知道,你一定认为这太疯狂了吧,但是这就是解决动态创建类的方法。非常简单地把类名字放进一个空类里,编译器就是加载它,即使在这个类里面没有任何的变量被定义。最后的事情是,定义一个该类的变量放到我们的文档类里。这里是代码:

  1. // This class forces the compiler to import your dynamic Classes
  2. var includeClasses:IncludeClasses;
复制代码

并确定你导入了这个:

  1.   
  2. import com.flashartofwar.example.IncludeClasses;
复制代码

现在再次运行你的项目,你会看到3个盒子通过XML动态得被初始化出来。这可不简单哦,你可以自己试着创建一个类,来创建绿盒子和蓝盒子,然后把它们加入到IncludeClasses类里面,然后再在XML文件中配置一下。他们会像红盒子这样被创建出来。当我们知道包路径和类名的时候,我希望使用getDefinitionByName的这个简单的例子可以让我们更简便地创建类。请在评论里自由的发言吧,并讨论你在自己的项目中是如何使用这个技巧的呢。

分享到:
评论

相关推荐

    本示例实现利用 XML 布局文件动态创建CheckBox

    本示例将详细介绍如何利用XML布局文件动态创建CheckBox。 首先,我们了解XML布局文件的基本结构。在Android中,每个XML布局文件通常包含一个根视图(如LinearLayout、RelativeLayout或ConstraintLayout)以及嵌套在...

    利用XML动态生成Flash

    本文将深入探讨如何利用XML动态生成Flash,以实现更加灵活和可扩展的内容展示。 首先,XML是一种标记语言,它允许我们以结构化的方式存储和传输数据。它的主要优点是数据与显示分离,这意味着我们可以独立地修改...

    XML 动态转换成类

    在.NET框架中,我们可以利用System.Xml.Serialization命名空间中的特性(Attributes)和类来完成这一转换。 首先,我们需要定义一个类,该类的属性对应XML文档中的元素和属性。例如,如果有一个XML文档如下: ```...

    动态创建xml问卷

    在这个场景中,"动态创建XML问卷"意味着程序可以根据需求动态生成XML结构来表示问卷,而不是预先硬编码问卷的问题和选项。下面将详细探讨这个主题。 1. **XML基础知识** - **XML元素**:XML文档由一系列元素构成,...

    C#,利用反射动态创建对象

    本篇文章将深入探讨如何利用反射在C#中动态创建对象。 1. **反射基础** 反射是.NET框架提供的一种特性,通过System.Reflection命名空间中的类来实现。主要类包括Assembly(程序集)、Type(类型)、...

    用C#与XML创建动态分层菜单.

    本文详细介绍了一种利用C#编程语言、XML数据格式以及Microsoft .NET框架来创建动态分层菜单的方法。这种菜单系统旨在模仿Windows系统的开始菜单布局,为用户提供更加直观且易于导航的Web体验。 #### XML与C#的结合 ...

    XML动态转化为ObjectDemo

    通过这个"XML动态转化为ObjectDemo",开发者可以深入理解XML在Java应用程序中的作用,以及如何利用JAXB或其他工具高效地进行XML数据的处理。这在进行数据交换、配置文件读取、Web服务交互等方面具有广泛的应用。

    xml动态生成窗体(源码)

    总的来说,利用XML动态生成窗体是一种实用的编程技巧,它结合了XML的数据描述能力与编程语言的动态创建对象的能力。这使得开发者能够灵活地设计和调整用户界面,而无需每次都手动编写大量的代码。如果你在实际项目中...

    C# 利用反射动态创建对象

    标题中提到的"利用反射动态创建对象",主要涉及到以下几个知识点: 1. **Activator.CreateInstance()**:这是最常用的动态创建对象的方法,属于SystemActivator类。它接受一个Type参数,该参数表示要创建的对象的...

    配置文件Xml XMl公共类

    ### 配置文件XML与XML...利用像`XmlHelper`这样的封装类,开发者可以更加高效地处理XML配置文件,实现数据的动态管理和灵活应用。在实际项目中,合理运用XML和相关的公共类,可以极大地提高软件的可配置性和维护性。

    xml帮助类,xml,C#

    结合`HttpPostedFileBase`类,你可以接收用户上传的XML文件,然后利用`XmlDocument`进行处理和分析。 在实际应用中,为了提高性能和减少内存占用,开发者可能会选择其他XML处理类,如`XDocument`(LINQ to XML)...

    利用XML实现通用WEB报表打印

    本篇文章将深入探讨如何利用XML来实现通用的WEB报表打印。 首先,我们需要理解XML的基本结构。XML文档由元素构成,每个元素都有开始标签和结束标签,例如`&lt;report&gt;`和`&lt;/report&gt;`。元素可以包含其他元素、文本或...

    tinyxml生成xml动态库

    "tinyxml生成xml动态库"指的是利用TinyXML库创建一个动态链接库(DLL),这样其他程序就可以通过调用这个库来处理XML操作,而无需包含完整的TinyXML源代码。 XML(eXtensible Markup Language)是一种标记语言,常...

    mybatis动态创建数据库表

    在“mybatis动态创建数据库表”这个主题中,我们将深入探讨如何利用MyBatis实现数据库表的动态创建、数据插入以及数据修改。 一、动态创建数据库表 MyBatis本身并不直接支持动态创建数据库表,但可以通过结合Spring...

    VS2005c#根据XML动态生成各种控件的例子

    【标题】"VS2005c#根据XML动态生成各种控件的例子"涉及的核心知识点是C#编程语言、XML数据解析以及Windows Forms应用程序中动态创建和管理控件。在这个例子中,开发者利用XML文件来定义UI元素的属性,如控件类型、...

    VB XML文件读取操作类.rar_vb xml_vb xml操作类_vb 安卓xml_xml_xml文件读取类

    不过,如果你在VB.NET环境中创建了XML处理的类,这些类可以通过.NET互操作性被用在使用.NET框架的Windows Phone或通用Windows平台应用中。对于Android,通常使用Java的DOM、SAX或Pull解析器来处理XML。 6. **实例...

    动态创建报表的五个类

    总的来说,动态创建rdlc报表的关键在于理解报表结构、设计合适的`ReportDefinition`,以及灵活运用生成器类来实现报表的XML构造。通过这样的方式,开发者可以快速响应业务需求的变化,创建出符合要求的定制化报表,...

    XML的读写 数据集 动态生成控件

    例如,如果从XML文件读取的数据包含多列,程序可能会动态创建多个TextBox或Label控件以显示这些数据。这通常涉及`Controls.Add()`方法,以及设置控件的相关属性如Text、Name、Size等。动态生成控件可以提高代码的...

    VS2005-XML动态菜单

    由于菜单项是动态创建的,所以可能需要使用`toolStripMenuItem.Click`事件的委托来处理。 5. **更新MenuStrip**:最后,调用MenuStrip的`Refresh()`方法,使其显示最新的菜单结构。 通过以上步骤,我们可以实现一...

    根据XML配置文件自动生成窗体控件

    这个解决方案利用XML文件作为配置源,通过编程语言的反射机制,实现动态创建和管理窗体上的控件,从而达到灵活应对采集内容变化的目的。 首先,我们来看XML配置文件。XML(eXtensible Markup Language)是一种结构...

Global site tag (gtag.js) - Google Analytics