在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. Python实现简单的API接口

    get方法 代码实现   # coding:utf-8       import json   from urlparse import parse_qs   from wsgiref.simple_ ...

  2. EventBus机制 handler 区别

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 事件巴士 是 采用 观察者模式 实现 事件订阅总线, 可以用在 应用程序中, 组件之间, ...

  3. BZOJ1084 SCOI2005最大子矩阵

    考虑DP f[i][j][k]表示一行到i一行到j共取k块最大值,类似于最长公共子序列n^2那种 注意相等时可以一起拿 By:大奕哥 #include<bits/stdc++.h> usi ...

  4. hdu 3949 XOR 线性基 第k小异或和

    题目链接 题意 给定\(n\)个数,对其每一个子集计算异或和,求第\(k\)小的异或和. 思路 先求得线性基. 同上题,转化为求其线性基的子集的第k小异或和. 结论 记\(n\)个数的线性基为向量组\ ...

  5. SpringBoot静态资源访问+拦截器+Thymeleaf模板引擎实现简单登陆

    在此记录一下这十几天的学习情况,卡在模板引擎这里已经是四天了. 对Springboot的配置有一个比较深刻的认识,在此和大家分享一下初学者入门Spring Boot的注意事项,如果是初学SpringB ...

  6. Problem A: 深入浅出学算法002-n个1

    Description 由n个1组成的整数能被K(K<10000)整除,n至少为多少? Input 多组测试数据,第一行输入整数T,表示组数 然后是T行,每行输入1个整数代表K Output 对 ...

  7. PHP -- 函数基础入门

    FROM : http://www.cnblogs.com/kym/archive/2010/02/14/1668300.html, http://www.cnblogs.com/kym/archiv ...

  8. python开发_random

    和java中的random()函数一样,在python中也有类似的模块random,即随机数 下面是我做的demo 运行效果: ==================================== ...

  9. bzoj 2957 楼房重建 分块

    楼房重建 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=29 ...

  10. 破解MyEclipse2015 stable3.0(亲测可用)

    整个破解过程最好断网: 1.安装好MyEclipse2015 stable3后,打开设置好工作目录后,退出.2.将plugins文件夹中的文件拷贝到myeclipse安装目录的plugins文件夹下, ...