在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;
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 之 生成元数据和代理的更多相关文章

  1. WCF公开服务元数据方式

    一般我们使用了scvutil命令自动生成了服务的客户端代理类: 例如:svcutil http://localhost:8000/?wsdl /o:FirstServiceClient.cs 命令中h ...

  2. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[扩展篇] 通过<实现篇>对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding ...

  3. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...

  4. 修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类

    折腾几天记载一下,由于项目实际需要,从edmx生成的实体类能自动继承自定义的基类,这个基类不是从edmx文件中添加的Entityobject. 利用ADO.NET C# POCO Entity Gen ...

  5. 利用反射生成JDK动态代理

    利用反射生成JDK动态代理 在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成JDK动态代理类和动态代理 ...

  6. JavaSE---使用反射生成JDK动态代理

    1.概述 1.1 在Java.lang.reflect包下,提供了Proxy类.InvocationHandler接口,使用它们可以生成JDK动态代理类或动态代理对象: 1.2 [Proxy类] 1. ...

  7. spring-boot如何生成元数据与javaBean进行关联用作配置文件提示

    spring-boot如何生成元数据与javaBean进行关联用作配置文件提示 首先需要引入一个jar依赖包,以及一个maven plugin如下所示 <dependency> <g ...

  8. Java基础之反射生成JDK动态代理

    在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口.通过这个类和接口可以生成JDK动态代理类或动态代理对象. JDK动态代理例子: / ...

  9. WCF服务引用之后自动生成的泛型代理类名称太长的解决方案

    问题:WCF服务引用之后会将原来的泛型类自动生成一个代理类,但是有时候名称太长怎么办? 解决方案: 1.方案一: 调用客户端同样也引用这个泛型类的类库. 2.方案二: 找到这个泛型类,然后在上面的[D ...

随机推荐

  1. 【十大经典数据挖掘算法】k

    [十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART 1. 引言 k-means与kNN虽 ...

  2. Linux中的mysql操作(2)

    1.终端启动MySQL:/etc/init.d/mysql start: 2.登录MySQL:mysql –u root -p (用root账户登录),然后输入密码: 3.查看所有的数据库名字:sho ...

  3. 【BZOJ 2728】 2728: [HNOI2012]与非 (线性基?)

    2728: [HNOI2012]与非 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 813  Solved: 389 Description Inpu ...

  4. RE:从零开始的AGC被虐(到)生活(不能自理)

    RE:从零开始的AGC被虐(到)生活(不能自理) 「一直注视着你,似近似远,总是触碰不到.」 --来自风平浪静的明天 AtCoder Grand Contest 001 B: Mysterious L ...

  5. ElasticSearch学习笔记--2、ES相关配置

    1.配置文件 ES的配置文件位置:config/elasticsearch.yml可以直接搜索elasticsearch.yml 2.配置远程api访问 network.host: 192.168.1 ...

  6. maven搭建企业级多模块项目

    1.创建一个maven项目 选择pom 完成 2.创建模块 项目右键选择module,创建模块.创建子模块 其余的打包时都为jar 地址:https://github.com/LeviFromCN/m ...

  7. bzoj1634护花

    试题描述: 约翰留下他的N(N<=100000)只奶牛上山采木.他离开的时候,她们像往常一样悠闲地在草场里吃草.可是,当他回来的时候,他看到了一幕惨剧:牛们正躲在他的花园里,啃食着他心爱的美丽花 ...

  8. PAT甲级1095. Cars on Campus

    PAT甲级1095. Cars on Campus 题意: 浙江大学有6个校区和很多门.从每个门口,我们可以收集穿过大门的汽车的进/出时间和车牌号码.现在有了所有的信息,你应该在任何特定的时间点告诉在 ...

  9. ExtJs 3 自定义combotree

    ExtJs 3 自定义combotree /** * 自定义下拉树,支持初始化值时自动定位树节点. * 还没有考虑性能问题.继承自Ext.form.ComboBox也很浪费. * 代码中的cu.get ...

  10. BR16F84 OBD II Interface Chip For PWM, VPW, and ISO 9141-2 Vehicles

    http://faq.ford77.ru/pdf/eec/DataSheet.pdf FEATURES:Operating Voltage 5.0 VOperating Current 5 Ma. T ...