Reflection

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

在本次实验中,你将会将一个普通的C/S程序移植为一个WCF的C/S程序。并且你也将会尝试不同的方式来完成WCF的配置工作,尝试不同的宿主方式和绑定设置。

经典Client/Server程序
打开Essentials文件夹下的WCFEssentials.sln解决方案。解决方案中包含了一个名字为MyClient的winform客户端和一个名为Service的类库。在Service project中可以看到MyService类实现了IMyContract:

public interface IMyContract
{
   
void
 MyMethod();
   
void
 MyOtherMethod();
}


public class MyService : IMyContract
{
   
public void
 MyMethod()
   
{      
      MessageBox.Show(
"MyMethod()","MyService"
);
   }

   
public void MyOtherMethod()
   
{
      MessageBox.Show(
"MyOtherMethod()","MyService"
);
   }

}

编译后运行客户端:

点击button不会有任何反应,因为button事件还没有添加任何代码。

关闭客户端。选择client项目并添加到service项目的引用。在client端的button click事件中添加如下代码:

void OnCallService(object sender,EventArgs e)
{
     IMyContract service 
= new
 MyService();
      service.MyMethod();
}

编译项目确保没有错误发生。

定义WCF服务
选择Service项目并添加引用到System.ServiceModel.dll。在MyService.cs文件中添加using语句:
using System.ServiceModel;
通过添加ServiceContract和OperationContract将IMyContract接口定义为WCF契约,并去掉public的定义:

[ServiceContract]
interface
 IMyContract
{
    [OperationContract]
    
void
 MyMethod();
    [OperationContract]
    
void
 MyOtherMethod();
}

同样去掉MyService的public定义:

宿主服务
我们将把服务宿主到一个控制台程序。选中service项目,并打开属性页。在Application页签中,选择Console Application作为输出类型:

下一步,在service项目中添加一个名为Program.cs的文件,并在其中添加main方法。并在main方法中添加宿主的代码:

using System.ServiceModel;

class
 Program
{
    
static void
 Main()
    
{
        Uri baseAddress 
= new Uri("http://localhost:8000/"
);
        ServiceHost host 
= new ServiceHost(typeof
(MyService), baseAddress);

        host.Open();
        Console.WriteLine(
"Host open. Type any key to close"
);
        Console.ReadLine();

        host.Close();
    }

}

配置服务
为service项目添加App.config文件(文件名必须为App.config)。并在配置文件中为服务添加三个endpoint:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<system.serviceModel>
    
<services>
      
<service name="MyService">
        
<endpoint 
          
address="MyService"
 
          binding
="wsHttpBinding"
 
          contract
="IMyContract" />

        
<endpoint 
          
address="http://localhost:8001/MyService/"
 
          binding
="wsHttpBinding"
 
          contract
="IMyContract" />

        
<endpoint 
          
address="net.tcp://localhost:8002/MyService/"
 
          binding
="netTcpBinding"
 
          contract
="IMyContract" />

      
</service>
    
</services>
  
</system.serviceModel>
</configuration>

将Metadata Exchange置为有效
为service添加属性,将Metadata Exchange置为有效:

<system.serviceModel>
  
<services>
    
<service name="MyService" behaviorConfiguration="MEX Enabled">
      ……
    
</service>
  
</services>
  
<behaviors>
    
<serviceBehaviors>
      
<behavior name="MEX Enabled">
        
<serviceMetadata httpGetEnabled="true"/>
      
</behavior>
    
</serviceBehaviors>
  
</behaviors>
</system.serviceModel>

客户端编码
将client项目中对service项目的引用移除,并添加对System.ServiceModel.dll的引用。
在client项目中添加名为Proxy的类。为了简单,我们将命名空间MyClient删除,并重命名Proxy类为MyContractClient:

using System.ServiceModel;

class MyContractClient
{
}

将contract的定义添加到proxy文件的顶部

[ServiceContract]
interface IMyContract
{
    [OperationContract]
    
void MyMethod();
    [OperationContract]
    
void MyOtherMethod();
}

class MyContractClient
{
}

将MyContractClient类修改为继承ClientBase<IMyContract>并实现接口IMyContract:

class MyContractClient : ClientBase<IMyContract>, IMyContract
{
    
public void
 MyMethod()
    
{
        Channel.MyMethod();
    }


    
public void MyOtherMethod()
    
{
        Channel.MyOtherMethod();
    }

}

修改client端的按钮事件,使用代理类来完成:

void OnCallService(object sender,EventArgs e)
{
  MyContractClient proxy 
= new
 MyContractClient();
  proxy.MyMethod();
  proxy.Close();
}

配置客户端
Client端我们将使用service端的TCP endpoint。为client项目添加App.config。并添加如下配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<system.serviceModel>
    
<client>
      
<endpoint 
        
address="net.tcp://localhost:8002/MyService/"
 
        binding
="netTcpBinding"
 
        contract
="IMyContract" />

    
</client>
  
</system.serviceModel>
</configuration>

测试应用程序
将解决方案设置为多项目启动,如图:

然后直接F5就可以了。

使用VS2008自动配置客户端
将解决方案设置为单项目启动,并把service项目设为启动项目。启动service但不要进入调试。为client项目添加service reference。在地址栏中输入
http://localhost:8000/,点击Go按钮:

点击OK后,VS2008会为你自动生成客户端代理在命名空间:MyClient.ServiceReference下。
在client项目中删除Proxy.cs。打开ClientForm.cs文件,并添加using语句:
using System.ServiceModel;
VS2008会重新修改配置文件。打开app.config并修改它为如下所示(很多东西是不需要的):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<system.serviceModel>
    
<client>
      
<endpoint 
        
address="net.tcp://localhost:8002/MyService/"
 
        binding
="netTcpBinding"

        contract
="ServiceReference.IMyContract"
        
/>
    
</client>
  
</system.serviceModel>
</configuration>

保存所有修改并编译后测试程序。

使用Channel Factory
使用channel factory,我们只需要一个interface的定义。打开Proxy.cs文件,删除MyContractClient类的定义。
在ClientForm.cs文件中,添加using语句:
using System.ServiceModel;
修改OnCallService方法,使用ChannelFactory<T>:

void OnCallService(object sender,EventArgs e)
{
    ChannelFactory
<IMyContract> factory = new ChannelFactory<IMyContract>(""
);
    IMyContract proxy 
=
 factory.CreateChannel();
    proxy.MyMethod();
    ICommunicationObject channel 
= proxy as
 ICommunicationObject;
    channel.Close();
}

编译并测试程序。

使用自动宿主工具
.NET3.5提供了两个简单的工具—WcfSvcHost.exe用于宿舍服务,WcfTestClient.exe用于测试client。下面我们将会同时使用它们。
在解决方案中删除client项目。
将service项目改为Class Library。

在Debug页签中,选中Start external program,并浏览到文件:C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ WcfSvcHost.exe。在Command line arguments中输入:/service:Service.dll /config:Service.dll.config /client:WcfTestClient.exe。如图:

接下来,在service项目中删除Program.cs文件。在config文件中需要添加base address:

<service name="MyService" behaviorConfiguration="MEX Enabled">
  
<host>
    
<baseAddresses>
      
<add baseAddress="http://localhost:8000/"/>
</baseAddresses>

</service>

接下来运行项目,在系统托盘会看到如下图标:

测试工具将会弹出:

在任意一个endpoint中选中MyMethod()方法,并点击Invoke按钮,就可以进行测试了。


posted on 2008-04-10 22:25  Reflection  阅读(874)  评论(4编辑  收藏  举报