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;
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还有很多的知识,今后的文章中在介绍。祝大家工作愉快!!!(完)

posted @ 2010-01-28 13:00  烟鬼  阅读(1831)  评论(1编辑  收藏  举报