WCF 之 生成元数据和代理
在WCF开发概述中讲解了手工方式的WCF应用,其实实际开发中使用更多的使用配置方式和元数据来实现WCF,下面我们来看一个具体的Demo,这个例子和WCF开发概述中使用的是同一个例子,只是实现方式不同,然后来再来讲解。
Demo
首先在Host项目中添加一个App.config文件,可以参照下图方式:

添加后工程如下:

App.config代码 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WCF.Demo.HelloWorldService" behaviorConfiguration="serviceBehavior">
<endpoint binding="wsHttpBinding" contract="WCF.Demo.IService" address="HelloWorld" />
<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9000"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
下面解释一下文件的内容:
service name="WCF.Demo.HelloWorldService"指定到Service类。
behaviorConfiguration="serviceBehavior"指定到下面的<ServiceBehaviors>。
<endpoint binding="wsHttpBinding" contract="WCF.Demo.IService" address="HelloWorld" />这个endpoint是指定Service的邦定方式和契约还有地址。
<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" />这个endpoint是WCF内建的邦定方式和契约,主要用来完成元数据的传递。
add baseAddress="http://localhost:9000" 这个指定访问Service的服务器地址
上面就把Service部分配置好了。
对于ServiceBehaviors部分很简单,serviceMetadata httpGetEnabled="true" 就表示Service可以采取http的Get方式来传递元数据。
由于已经通过配置的方式,是实现了endpoint的东西,所以host.cs中就不用再添加和定义endpoint了。
Host.cs代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; namespace WCF.Demo
{
public class Host
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(WCF.Demo.HelloWorldService)))
{
host.Open();
Console.WriteLine("Host in started successful!");
Console.Read();
}
}
}
}
现在启动host程序,程序可以成功运行。
并且由于配置了http相关的访问方式和协议,此时我们可以通过IE中输入 http://localhost:9000/来查看这个Sevice的相关信息。
信息如下:
******************************************************************************************************
HelloWorldService Service
You have created a service.
To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:
svcutil.exe http://localhost:9000/?wsdl
This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:
C#
class Test
{
static void Main()
{
ServiceClient client = new ServiceClient(); // Use the 'client' variable to call operations on the service. // Always close the client.
client.Close();
}
}
Visual Basic
Class Test
Shared Sub Main()
Dim client As ServiceClient = New ServiceClient()
' Use the 'client' variable to call operations on the service. ' Always close the client.
client.Close()
End Sub
End Class
******************************************************************************************************
为什么不是http://localhost:9000/HelloWorld那?点击上边的http://localhost:9000/?wsdl 可以查看这个Service的WSDL描述,
你会发现HelloWorld其实是在真正调用Service通信是的地址,它是内部使用的。
现在扫除两个概念问题:
WSDL:Web Services Description Language的缩写,是一个用来描述Web服务和说明如何与Web服务通信的XML语言。怎样向别人介绍你的Web service有什么功能,
以及每个函数调用时的参数呢?你可能会自己写一套文档,你甚至可能会口头上告诉需要使用你的Web service的人。这些非正式的方法至少都有一个严重的问题:
当程序员坐到电脑前,想要使用你的Web service的时候,他们的工具(如Visual Studio)无法给他们提供任何帮助,
因为这些工具根本就不了解你的Web service。解决方法是:用机器能阅读的方式提供一个正式的描述文档。
Web service描述语言(WSDL)就是这样一个基于XML的语言,用于描述Web service及其函数、参数和返回值。因为是基于XML的,
所以WSDL既是机器可阅读的,又是人可阅读的,这将是一个很大的好处。一些最新的开发工具既能根据你的Web service生成WSDL文档,
又能导入WSDL文档,生成调用相应Web service的代码。
元数据:元数据最本质、最抽象的定义为:data about data (关于数据的数据)。它是一种广泛存在的现象,
在许多领域有其具体的定义和应用。在软件构造领域,元数据被定义为:在程序中不是被加工的对象,而是通过其值的改变来改变程序的行为的数据。
它在运行过程中起着以解释方式控制程序行为的作用。在程序的不同位置配置不同值的元数据,就可以得到与原来等价的程序行为。
元数据是一种二进制信息,用以对存储在公共语言运行库可移植可执行文件 (PE) 文件或存储在内存中的程序进行描述。
将您的代码编译为 PE 文件时,便会将元数据插入到该文件的一部分中,而将代码转换为 Microsoft 中间语言 (MSIL) 并将其插入到该文件的另一部分中。
在模块或程序集中定义和引用的每个类型和成员都将在元数据中进行说明。当执行代码时,运行库将元数据加载到内存中,
并引用它来发现有关代码的类、成员、继承等信息。
其实使用配置方式是不需要编写代码的。
本例中的Service不变:

Service.cs代码
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF.Demo
{
[ServiceContract(Namespace="http://www.cnblogs.com/charlesliu")]
public interface IService
{
[OperationContract]
string HelloWorld(string message);
}
public class HelloWorldService : IService
{
public string HelloWorld(string message)
{
return string.Format("At {0}, I will say {1}", DateTime.Now, message);
}
}
}
下面来看看Client端如何使用这个服务,首先把Service启动起来,然后在Client工程中添加一个Service的引用。
如果添加Service引用的时候出现下面的问题,可以用这个命令来解决:D:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe /resetskippkgs

正常情况下可以看到下面的对话框:

此时Client工程会变成下图,很多东西已经自动创建了,其会根据WSDL自动生成相应的Proxy文件和配置文件。可以显示所有文件然后查看,其中Reference.cs就是Proxy文件。

修改namespace为SRHelloWorld,原因是自动生成的namespace自动加了Client.前缀(代码中的相关引用也要对应的改掉),和程序定义的Client冲突了(如果没有名字冲突问题可以不考虑这个)。然后可以在Cleint.cs中调用相关的对象和方法了。
因为配置文件和代理文件都是自动生成的,所以大大简化了客户端的编成方式。若个Service发生了变化,可以重新运行host程序,然后再client的Service Reference下的那个绿色的引用上右击鼠标选择Update Service Reference即可。
Client.cs代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; namespace WCF.Demo
{
class Client
{
static void Main(string[] args)
{
SRHelloWorld.ServiceClient proxy = new SRHelloWorld.ServiceClient();
string message = proxy.HelloWorld("Hello, World");
Console.WriteLine(message);
Console.Read();
}
}
}
运行Client程序,一切正常,服务调用成功,并返回了结果。
下面对于这个配置方式作一下总结,请看下图:

对于上面的图不再做过多说明了,其实就是实现了Service和Client的松耦合。Client并不直接与Service或者Endpoint交互,而是通过WSDL以元数据的方式通信,也就说只要WSDL不变化,Client就不会受到影响,
即使Service或者Ednpoint变化了。
到目前为止就把WCF的原理和开发方式介绍完了,具体到WCF还有很多的知识,今后的文章中在介绍。祝大家工作愉快!!!(完)
WCF 之 生成元数据和代理的更多相关文章
- WCF公开服务元数据方式
一般我们使用了scvutil命令自动生成了服务的客户端代理类: 例如:svcutil http://localhost:8000/?wsdl /o:FirstServiceClient.cs 命令中h ...
- WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇]
原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇] 通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding ...
- WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]
原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...
- 修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类
折腾几天记载一下,由于项目实际需要,从edmx生成的实体类能自动继承自定义的基类,这个基类不是从edmx文件中添加的Entityobject. 利用ADO.NET C# POCO Entity Gen ...
- 利用反射生成JDK动态代理
利用反射生成JDK动态代理 在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成JDK动态代理类和动态代理 ...
- JavaSE---使用反射生成JDK动态代理
1.概述 1.1 在Java.lang.reflect包下,提供了Proxy类.InvocationHandler接口,使用它们可以生成JDK动态代理类或动态代理对象: 1.2 [Proxy类] 1. ...
- spring-boot如何生成元数据与javaBean进行关联用作配置文件提示
spring-boot如何生成元数据与javaBean进行关联用作配置文件提示 首先需要引入一个jar依赖包,以及一个maven plugin如下所示 <dependency> <g ...
- Java基础之反射生成JDK动态代理
在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口.通过这个类和接口可以生成JDK动态代理类或动态代理对象. JDK动态代理例子: / ...
- WCF服务引用之后自动生成的泛型代理类名称太长的解决方案
问题:WCF服务引用之后会将原来的泛型类自动生成一个代理类,但是有时候名称太长怎么办? 解决方案: 1.方案一: 调用客户端同样也引用这个泛型类的类库. 2.方案二: 找到这个泛型类,然后在上面的[D ...
随机推荐
- saltstack 开发
最近跟总部一个项目用saltstack封装api来用,可以很轻松的实现restful api发布,提供别人直接调用 salt 本身有2个内置变量(__salt__, __opts__),通过salt ...
- Hibernate fetching strategies(抓取策略)
抓取策略(fetching strategies)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hibernate如何获取关联对象的策略.抓取策略可以在O/R映射的 ...
- luoguP3714 [BJOI2017]树的难题 点分治
以后传数组绝对用指针... 考虑点分治 在点分的时候,把相同的颜色的在一起合并 之后,把不同颜色依次合并 我们可以用单调队列做到单次合并$O(n + m)$ 如果我们按照深度大小来合并,那么由于每次都 ...
- [BZOJ4240]有趣的家庭菜园(贪心+树状数组)
最后数列一定是单峰的,问题就是最小化最后的位置序列的逆序对数. 从大到小加数,每次贪心看放左边和右边哪个产生的逆序对数更少,树状数组即可. 由于大数放哪对小数不产生影响,所以正确性显然. 注意相同数之 ...
- HDU 6141 I am your Father!(最小树形图)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6141 [题目大意] 给出一个有向图,求1点为根的最小树形图使得第n个点的直接父亲编号最小 [题解] ...
- Centos7 下mysql大小写敏感问题
在Centos7 下mysql大小写敏感问题,会导致程序运行时找不到对应的表. 解决办法: 第一步:编辑/etc/my.cnf文件,在[mysqld]节下 添加 lower_case_table_na ...
- slf4j使用
pom jar包引用<!-- Logging --> <dependency> <groupId>ch.qos.logback</groupId> &l ...
- Vue学习记录-画页面
webstorm 因为之前开发ReactNative的时候,选择了webstorm,这回转战Vue,自然还是用它.如果什么也不做的话,打开Vue工程,编辑区域基本上没有语法高亮.怎么办呢? 安装插件( ...
- InvalidateRect()与Invalidate()的用法(转)
BOOL InvalidateRect( HWND hWnd, // 窗口句柄 CONST RECT* lpRect, // 矩形区域 BOOL bErase ...
- TPS61175/TPS55340 3A/5A、40V 电流模式集成 FET 升压 DC/DC 转换器
集成型5A 40V 宽输入范围升压/单端初级电感转换器(SEPIC) / 反激式(Flyback) 直流到直流稳压器 (Rev. B) 描述 TPS55340 是一款单片非同步开关稳压器,此稳压器带有 ...