很久没有写博客了,最近一直忙考试,只是被悲催的数学物理方程真的把我给伤着了.....

忙完了考试,又开始了导师的项目,然而发现项目的很多东西,用原始的ArcGIS Api for Silverlight根本无法实现。于是开始接触强大的ArcObject。虽然之前接触过一些ArcGIS Engine,但还是觉得学的云里雾里的,现在都忘得差不多了,于是又一次的被AO给伤了。

本文算是自己初学AO的一点总结吧,在此和大家分享,不对之处,恳请指教。

一、Silverlight调用AO需要什么?

  • 安装ArcOjects for .net Framework
  • 需要借助WCF或者WebService
  • 在Web项目中添加ArcGIS引用

关于AO的基本知识,本人初学,在此就不卖弄了。可以查看官方的帮助文档,前提是你需要一定的英语知识。

ArcObject官方在线文档:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html

关于WCF和WebService,本人觉得用法差不多,但是WCF要更强大一些,所以建议使用WCF。至于什么是WCF或者WebService可以参考微软的官方文档:

WCF官方文档及示例:

http://msdn.microsoft.com/en-us/library/dd456779.aspx

二、实现过程

我们这实现的功能很简单,就是获得某一地图服务(MapServer)下的所有图层。例如本文的发布的地图服务如下:

那么我们可以知道这里又是个图层(Layers):

下面我们就通过调用AO的方式获取这些图层。

1.新建Silverlight项目

选中Enable WCF RIA Service

2.在Web项目中添加ArcGIS相关的引用,如下图所示:

3.在Web项目中添加Silverlight-enabled WCF Service

选择Silverlight-enabled WCF Service,并设置服务名称,点击Add

此时Web部分的基本工作已经完成,接下来看看WCF服务器端如何实现。

 4.WCF端实现的代码

首先我们需要连接到GIS服务,例如之前说的MapService,然后才能获取该服务的所有图层,连接到GIS服务的大致过程如下图所示:

关于连接GIS服务器的详细说明,可参考ESRI中国社区diligentpig的这篇文章:

http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=42676

以及官网的指导说明:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Connecting_to_a_GIS_server/000100000200000000/

(1):WCF服务器端的连接代码:

首先添加如下引用:

using ESRI.ArcGIS.Carto;  using ESRI.ArcGIS.esriSystem;  using ESRI.ArcGIS.Server;  using ESRI.ArcGIS.Geodatabase;  using ESRI.ArcGIS.Geometry;  using System.Text;  using ESRI.ArcGIS.Location;

 

并定义如下变量:

 //用来存储GIS服务所有图层的名称          public string[] LayerName = null;          //获得主机的SOM对象          public ESRI.ArcGIS.Server.IServerObjectManager pSOM = null;          //获取GIS服务的Context          public ESRI.ArcGIS.Server.IServerContext pServerContext = null;          //服务器连接          ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsconnection = null;          //身份识别          ESRI.ArcGIS.ADF.Identity identity = null;          //GIS服务          ESRI.ArcGIS.Carto.IMapServer2 pMapServer=null;          //GIS服务的对象          ESRI.ArcGIS.Carto.IMapServerObjects2 pMapServerObject = null;          //GIS服务对象对应的地图,包含服务的所有图层          ESRI.ArcGIS.Carto.IMap pMap = null;

 

然后再WCF的构造函数中实例化:

 //设置用户名,密码及域名               identity = new ESRI.ArcGIS.ADF.Identity("ArcGISWebServices", "quzijing", "qzj");              //设置服务地址              agsconnection = new                  ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection("localhost", identity);              agsconnection.Connect();              pSOM = agsconnection.ServerObjectManager;              //指定相应GIS服务的地址,以及GIS服务的类型              pServerContext = pSOM.CreateServerContext("NetworkAnalystServiceFolder/RiverMap", "MapServer");              //创建GIS服务对象及Map              pMapServer = pServerContext.ServerObject as ESRI.ArcGIS.Carto.IMapServer2;              pMapServerObject = pMapServer as ESRI.ArcGIS.Carto.IMapServerObjects2;              pMap = pMapServerObject.get_Map(pMapServer.DefaultMapName);

 

这里需要说明的是:

a.identify的设置。和我们的ArcGIS Server Manager的UserName(用户名),Domain(域名),Password(密码)一致。

b.设置ArcGIS Server服务器地址:一般我们使用localhost即可,也可使用ip地址,当部署应用程序的时候建议使用IP地址。

c.指定GIS服务地址及服务类型:

GIS服务地址是相对于我们ArcGIS Server服务器根目录来说的,假设我们已有的GIS服务如下图所示:

那么如果我们想连接ChinaMap对应的MapServer时,使用的地址则直接是:ChinaMap,相应的代码为:

pServerContext = pSOM.CreateServerContext("ChinaMap", "MapServer");

而如果是要获取RiverMap对应的MapServer时,那么需要指定其相对于GIS服务的路径,即:NetworkAnalystServiceFolder/RiverMap,示例代码则为:

 pServerContext = pSOM.CreateServerContext("NetworkAnalystServiceFolder/RiverMap", "MapServer");

同时还需要注意的问题是第二个参数中的GIS服务类型必须一致。

(2).获取图层名称。

上面我们已经获得了指定服务的Map,通过该Map我们即可获得Map中包含的所有图层,示例代码如下:

 if (pMap.LayerCount > 0)              {                  LayerName = new string[pMap.LayerCount];                  for (int i = 0; i < pMap.LayerCount; i++)                  {                      ILayer layer = pMap.Layer[i];                      LayerName[i] = string.Format("Map Layer {0}:{1}", i, layer.Name);                  }              }

此外,我们个还可以获得指定的图层以及其中的要素,示例代码:

            IFeatureClass pFC = (pMap.get_Layer(1) as ESRI.ArcGIS.Carto.IFeatureLayer).FeatureClass;              IFeatureCursor pPolyLineCursor = pFC.Search(null, false);              IFeature pPolyFeature = pPolyLineCursor.NextFeature();

(3).定义WCF实现服务的契约

该契约方法返回制定GIS服务中所有的图层名称,即返回上面的LayerName字符数组,示例代码如下:

       [OperationContract]          public string []GetLayerString()          {              if(LayerName==null)              {                  LayerName = new string[1];                  LayerName[0] = "错误:没有获得图层";              }              return LayerName;          }

以上过程我们便完成了服务器端的工作,接下来我们看看客户端的实现。

5.客户端的实现

首先添加WCF服务引用

此时我们的项目文件结构如下所示:

接下来实现客户端的功能,客户端的实现很简单,我们这里就只是获得制定GIS服务所有的图层名称,我们定义一个Button和一个ListBox

 <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="83,23,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />          <ListBox Margin="12,61,172,0" Name="listBox1" VerticalAlignment="Top" HorizontalAlignment="Left" />    

后台代码:

 AOServiceReference.ArcGIS_AOServiceClient client = new ArcGIS_AOServiceClient();          public MainPage()          {              InitializeComponent();              client.GetLayerStringCompleted += new EventHandler<GetLayerStringCompletedEventArgs>(client_GetLayerStringCompleted);          }            void client_GetLayerStringCompleted(object sender, GetLayerStringCompletedEventArgs e)          {              //将WCF结果绑定到ListBox              listBox1.ItemsSource = e.Result;          }            private void button1_Click(object sender, RoutedEventArgs e)          {              client.GetLayerStringAsync();          }

最后的效果:

点击Button,获得图层列表

 

 (版权所有,转载请标明出处)