这几天想把SharpMap的数据源改为服务器向客户端提供数据,看到园子里很多朋友在研究WCF.故而心痒难耐,也想赶一把时髦!
WCF的构架图:
![](https://www.cnblogs.com/images/cnblogs_com/ali/WCFStaging.jpg)
应用到项目中的层次模型:
![](https://www.cnblogs.com/images/cnblogs_com/ali/Staging.jpg)
相信各位看官通过名字就可以了解他的层次了 .
Contract就是WCF中最重要的数据契约层了.其代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
[ServiceContract]
2
public interface IGetData
3![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
4
//获取图片目录
5
[OperationContract]
6
string GetPICAddress();
7![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
//获取VectorLayer样式
9
[OperationContract]
10
byte[] GetVStyleAddress(string DataBase,ref int VLayerCount);
11![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
//获取LableLayer样式
13
[OperationContract]
14
byte[] GetLStyleAddress(string DataBase, ref int LLayerCount);
15![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
//读取XML文档(样式表单)
17
[OperationContract]
18
byte[] ReadXML(string DataBase, string XMLName);
19![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
//读取XML文档(更换地图源)
21
[OperationContract]
22
byte[] MapDataBase(string address);
23![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
//获取VectorLayer地图数据源
25
[OperationContract]
26
byte[] GetMapDataSource(GetVDataSource VDataSource);
27
}
作为Service,在Contract上签字的方式就是实现这样的一个Interface。下面的Service得到code
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
public class GetData : IGetData
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
Create create = new Create();
4![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
IGetData 成员#region IGetData 成员
6![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
public string GetPICAddress()
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
9
return "http://www.cnblogs.com/Config/Style/pic/";
10
}
11![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
public byte[] GetVStyleAddress(string DataBase, ref int VLayerCount)
13![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14
return Compression.SerializeData(create.GetLayers("http://www.cnblogs.com/Config/Style/" + DataBase + "/VectorLayerXML.xml", ref VLayerCount));
15
}
16![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
public byte[] GetLStyleAddress(string DataBase, ref int LLayerCount)
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
19
return Compression.SerializeData(create.GetLayers("http://www.cnblogs.com/Config/Style/" + DataBase + "/LableLayerXML.xml", ref LLayerCount));
20
}
21![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
public byte[] ReadXML(string DataBase, string XMLName)
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
24
return Compression.SerializeData(create.ReadXML("http://www.cnblogs.com/Config/Style/" + DataBase + "/" + XMLName + ".xml"));
25
}
26![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
public byte[] MapDataBase(string address)
28![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
return Compression.SerializeData(create.ReadXML(address));
30
}
31![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
public byte[] GetMapDataSource(GetVDataSource VDataSource)
33![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
IProvider data=new MsSql(VDataSource.ConnStr, VDataSource.TableName, VDataSource.GeometryColumnName, VDataSource.OID_ColumnName);
35
return Compression.SerializeData(data);
36
}
37![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
#endregion
39
}
以上的内容是不是很简单,这样我们只需要一个宿主.也就是将这些服务提供给客户端的服务源.
Host的本质就是把一个Service 置于一个运行中的进程中,并以Endpoint的形式暴露出来,并开始监听来自Client端的请求。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
static void Main(string[] args)
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
using (ServiceHost GetDataHost = new ServiceHost(typeof(GetData)))
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
5![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
GetDataHost.Opened += delegate
{ Console.WriteLine("Calculator Service begin to listen via the Address:{0}", GetDataHost.BaseAddresses[0].ToString()); };
6
GetDataHost.Open();
7
Console.Read();
8
}
9
}
这里重中之重的就是App.config文件了.其实我们也可以不用它,只是这样可以避免程序的改动所带来的系统重新编译.比如我们把原来存在Intranet的Service放到Internet上,原来可能基于TCP的Binding必须改成基于Http的Binding,在这种情况下,我们依然可修改配置文件就可以了,这样的改动通常是很小的,并且修改了配置文件之后我们不需要对现有的代码进行重编译和重部署,它们可以其实生效。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
<?xml version="1.0" encoding="utf-8" ?>
2
<configuration>
3
<system.serviceModel>
4
<services>
5
<service name="SharpMap.WCFService.Service.GetData" behaviorConfiguration="GetDataBehavior">
6
<host>
7
<baseAddresses>
8
<add baseAddress="http://127.0.0.1:8888/GetData"/>
9
</baseAddresses>
10
</host>
11
<endpoint address="" binding="basicHttpBinding" contract="SharpMap.WCFService.Contract.IGetData" />
12
</service>
13
</services>
14
<behaviors>
15
<serviceBehaviors>
16
<behavior name="GetDataBehavior">
17
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
18
</behavior>
19
</serviceBehaviors>
20
</behaviors>
21
</system.serviceModel>
22
</configuration>
通过以上的代码我们就构建出了一个提供SharpMap地图数据传输的服务器端.那么我们怎么才能获得这些服务呢?
其实也很简单,只需要在客户端编写一个类继承Contract中的接口。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
public class WCFClient : ClientBase<IGetData>,IGetData
{
internal WCFClient():base(){}
#region IGetData 成员
//获取图片地址
public string GetPICAddress()
{
return this.Channel.GetPICAddress();
}
//获取VectorLayer样式列表
public byte[] GetVStyleAddress(string DataBase, ref int VLayerCount)
{
return this.Channel.GetVStyleAddress(DataBase,ref VLayerCount);
}
//获取LabelLayer样式列表
public byte[] GetLStyleAddress(string DataBase, ref int LLayerCount)
{
return this.Channel.GetLStyleAddress(DataBase, ref LLayerCount);
}
//获取地图渲染列表
public byte[] ReadXML(string DataBase, string XMLName)
{
return this.Channel.ReadXML(DataBase, XMLName);
}
//获取地图数据源
public byte[] MapDataBase(string address)
{
return this.Channel.MapDataBase(address);
}
//返回地图连接地址
public byte[] GetMapDataSource(GetVDataSource VDataSource)
{
return this.Channel.GetMapDataSource(VDataSource);
}
#endregion
//返回VectorLayer样式列表
public DataSet GetVStyle(string DataBase, ref int VLayerCount)
{
return (DataSet)Compression.DeserializeData(GetVStyleAddress(DataBase, ref VLayerCount));
}
//返回地图渲染列表
public DataSet GetXML(string DataBase, string XMLName)
{
return (DataSet)Compression.DeserializeData(ReadXML(DataBase, XMLName));
}
//返回LabelLayer样式列表
public DataSet GetLStyle(string DataBase, ref int LLayerCount)
{
return (DataSet)Compression.DeserializeData(GetLStyleAddress(DataBase, ref LLayerCount));
}
}
哈哈是不是很简单。可是我们还需要在客户端写一个App.config文件。
他的作用是通过App.config文件来获取Hosting提供的服务。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
<?xml version="1.0" encoding="utf-8" ?>
2
<configuration>
3
<system.serviceModel>
4
<client>
5
<endpoint address="http://127.0.0.1:8888/GetData" contract="SharpMap.WCFService.Contract.IGetData" binding="basicHttpBinding"/>
6
</client>
7
</system.serviceModel>
8
</configuration>
现在可以说是大功告成了!
由于是第一次实验,对WCF的很多功能上不是很了解。希望大家拍砖,以便于我的进步!
参考资源
[原创]我的WCF之旅(1):创建一个简单的WCF程序