AMF(Action Message Format)在开发Flash/Flex应用中使用频率是非常高的,相对普通的HTTP、WebService的SOAP等多种数据通信方式的效率更高,有人曾经做过这方面的测试,详细可以访问:​​http://xinsync.xju.edu.cn/index.php/archives/2162​​。本文将结合FluorineFx来提供通信服务接口,在客户端通过Flex来访问,简单的介绍下关于使用FluorineFx的AMF(Action Message Format)协议通信的用法。

      首先建立一个FluorineFx服务库,并建立一个数据传输对象(DTO),为该对象添加[FluorineFx.TransferObject]表示该对象可以用作于FluorineFx的数据传输对象,这个对象将会在本文后面用到,如下代码块:


namespace FxDotNet.Services.DTO

{

    [FluorineFx.TransferObject]

    public class Book

    {

        public int ID { get; set; }

        public string Name { get; set; }

        public string Author { get; set; }

        public double Price { get; set; }


        public Book()

        { }


        public Book(int id, string name, string author, double price)

        {

            this.ID = id;

            this.Name = name;

            this.Author = author;

            this.Price = price;

        }

    }

}


 

      接下来就需要提供一个FluorineFx的远程服务(即标记有[RemotingService]的对象),通过该服务提供对外访问的方法接口,如下代码块:


namespace FxDotNet.Services

{

    [RemotingService]

    public class DataServices

    {

        public DataServices()

        {

        }


        /// <summary>

        /// 获取服务端的系统时间

        /// </summary>

        /// <returns></returns>

        public string GetServerTime()

        {

            return DateTime.Now.ToString();

        }


        public ArrayCollection GetBooks()

        {

            ArrayCollection array = new ArrayCollection();

            array.Add(new Book(1, "三国演义", "罗贯中", 100.00));

            array.Add(new Book(2, "西游记", "吴承恩", 200.00));

            array.Add(new Book(3, "水浒传", "施耐庵", 300.00));

            array.Add(new Book(4, "红楼梦", "曹雪芹", 400.00));


            return array;

        }

    }

}


      通过FluorineFx网站来宿主该远程服务,通过Flex的配置文件services-config.xml配置远程访问的AMF连接通道。


<channels>

        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">

            <endpoint uri="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>

            <properties>

            </properties>

        </channel-definition>

</channels>


 

       FluorineFx提供的远程服务(RemotingService),使用Flex、Flash或Silverlight开发的客户端都是可以访问的,要实现客户端的远程调用其实是很简单的,这里以Flex作为示例进行演示,设置通信协议为AMF3,然后直接调用当前连接到服务器端连接对象的call()方法就可以实现远程调用,详细请查看下面完整的Flex示例。


<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" fontSize="12">

    <mx:Script>

        <![CDATA[

            import mx.collections.ArrayCollection;

            import mx.controls.List;

            import mx.rpc.events.FaultEvent;

            import mx.rpc.events.ResultEvent;

            private var nc:NetConnection;

            private var rs:Responder;

        

            private function init():void

            {

                nc = new NetConnection();

                rs = new Responder(onResult,onStatus);

            

                nc.objectEncoding = ObjectEncoding.AMF3;

                nc.connect("http://localhost:2311/FxDotNet.Web/Gateway.aspx");

                nc.client = this;

            }

            

            private function onResult(result:String):void

            {

                this.lbServerTime.text = "服务端系统时间为:" + result;

            }

            

            private function onStatus(event:Object):void

            {

                trace("Error");

            }

            

            private function getServerTime(event:MouseEvent):void

            {

                //服务器端所提供的RemotingService的全限定名

                nc.call("FxDotNet.Services.DataServices.GetServerTime",rs);

            }        

        ]]>

    </mx:Script>

    <mx:Button x="19" y="28" label="获取服务器系统时间" click="getServerTime(event)"/>

    <mx:Label x="19" y="60" width="402" id="lbServerTime"/>

</mx:Application>


 

      同样可以使用AMF来做大数据的传输,比如要传递一个集合、数组、DataTable或是DataSet等,下面以集合做为示例演示,ActionScript 3.0中新增了ArrayCollectin类,FluorineFx在服务器端对ActionScript 3.0的ArrayCollection对进行了序列化映射封装,服务端FluorineFx.AMF3.ArrayCollection类型的对象可以直接被客户端的ArrayCollection所接收。

      如上面FluorineFx所提供的远程服务接口中的GetBooks()方法,Flex调用此方法就会得到一个ArrayCollection对象,通过调试跟踪返回的数据可以很清楚的分析这些数据,如下图示:

                  

 

      详细请看下面的Flex完整示例代码:


<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12" 

    width="541" height="302" creationComplete="init()">

    <mx:Script>

        <![CDATA[

            import mx.collections.ArrayCollection;

            import mx.controls.List;

            import mx.rpc.events.FaultEvent;

            import mx.rpc.events.ResultEvent;

            private var nc:NetConnection;

            private var rs:Responder;

        

            private function init():void

            {

                nc = new NetConnection();

                rs = new Responder(onResult,onFault);

            

                nc.objectEncoding = ObjectEncoding.AMF3;

                nc.connect("http://localhost:2311/FxDotNet.Web/Gateway.aspx");

                nc.client = this;

            }

            

            private function getBook(event:MouseEvent):void

            {

                nc.call("FxDotNet.Services.DataServices.GetBooks",rs);

            }

            

            private function onResult(result:ArrayCollection):void

            {

                this.bookGrid.dataProvider = result;

            }

            

            private function onFault(event:Object):void

            {

                trace("Error");

            }

        ]]>

    </mx:Script>

    

    <mx:Button x="44" y="46" label="获取图书信息" click="getBook(event)"/>

     <mx:DataGrid x="44" y="78" id="bookGrid">

          <mx:columns>

              <mx:DataGridColumn headerText="编号" dataField="ID"/>

              <mx:DataGridColumn headerText="书名" dataField="Name"/>

              <mx:DataGridColumn headerText="作者" dataField="Author"/>

              <mx:DataGridColumn headerText="价格" dataField="Price"/>

          </mx:columns>

      </mx:DataGrid>

</mx:Application>


 

      除了使用FluorineFx所提供的ArrayCollection外,同样可以使用我们熟悉的Object[],List<Object>,DataTable等常用类型来作为数据返回的类型,其中Object[]和List<Object>类型的数据返回到客户段能够直接被客户端所接收,如下使用Object[]作数据返回类型的代码块:

 


/*************服务端方法*************/

public Book[] GetBookArray()

{

    Book[] book = new Book[]

    {

        new Book(1, "三国演义", "罗贯中", 100.00),

        new Book(2, "西游记", "吴承恩", 200.00),

        new Book(3, "水浒传", "施耐庵", 300.00),

        new Book(4, "红楼梦", "曹雪芹", 400.00)

    };

    return book;

}

/*************客户端方法*************/

private function onResult(result:Array):void

{

   //

}


 

      下面是以List<Object>类型返回的代码示例代码,客户段可以使用ArrayCollection直接接收:

 


/*************服务端方法*************/

/// <summary>

/// 以泛型类型返回给客户端

/// </summary>

/// <returns></returns>

public List<Book> GetBookList()

{

    List<Book> list = new List<Book>

    {

        new Book(1, "三国演义", "罗贯中", 100.00),

        new Book(2, "西游记", "吴承恩", 200.00),

        new Book(3, "水浒传", "施耐庵", 300.00),

        new Book(4, "红楼梦", "曹雪芹", 400.00)

    };

    return list;

}

/*************客户端方法*************/

private function onResult(result:ArrayCollection):void

{

   //

}


 

      如果要使用DataTable类型做方法的数据返回类型就需要注意下,服务器端直接返回DataTable类型的数据客户端是不能直接接收解析的,要使客户断方便解析所返回的DataTable类型数据,FluorineFx提供了DataTableTypeAttribute,为返回DataTable类型的方法加上DataTableTypeAttribute后返回给客户端,客户端就可以直接使用ArrayCollection接收了。

 


Flex与.NET互操作(十四):FluorineFx的AMF协议通信_xml

/******************服务端方法***********************/

[DataTableType("Book", "FxDotNet.Services.DTO.Book")]

public DataTable GetBookTable()

{

     DataTable dt = new DataTable("Book");

     dt.Columns.Add("ID", typeof(int));

     dt.Columns.Add("Name", typeof(string));

     dt.Columns.Add("Author", typeof(string));

     dt.Columns.Add("Price", typeof(double));


     DataRow dr = dt.NewRow();

     dr["ID"] = 1;

     dr["Name"] = "《三国演义》";

     dr["Author"] = "罗贯中";

     dr["Price"] = 100.00;

     dt.Rows.Add(dr);


     dr = dt.NewRow();

     dr["ID"] = 2;

     dr["Name"] = "《西游记》";

     dr["Author"] = "吴承恩";

     dr["Price"] = 200.00;

     dt.Rows.Add(dr);


     dr = dt.NewRow();

     dr["ID"] = 3;

     dr["Name"] = "《水浒传》";

     dr["Author"] = "施耐庵";

     dr["Price"] = 300.00;

     dt.Rows.Add(dr);


     dr = dt.NewRow();

     dr["ID"] = 4;

     dr["Name"] = "《红楼梦》";

     dr["Author"] = "曹雪芹";

     dr["Price"] = 400.00;

     dt.Rows.Add(dr);


     return dt;

}

/******************客户端方法***********************/

private function onResult(result:ArrayCollection):void

{

    //do other

}


 

​​