惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
F
Full Disclosure
博客园 - 【当耐特】
博客园 - 司徒正美
V
Visual Studio Blog
F
Fortinet All Blogs
T
Tor Project blog
T
Threatpost
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
C
Cyber Attacks, Cyber Crime and Cyber Security
阮一峰的网络日志
阮一峰的网络日志
GbyAI
GbyAI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tenable Blog
M
MIT News - Artificial intelligence
L
Lohrmann on Cybersecurity
P
Palo Alto Networks Blog
I
Intezer
Stack Overflow Blog
Stack Overflow Blog
The Register - Security
The Register - Security
The Last Watchdog
The Last Watchdog
S
Securelist
T
Tailwind CSS Blog
V
Vulnerabilities – Threatpost
U
Unit 42
博客园 - 叶小钗
P
Proofpoint News Feed
C
Cybersecurity and Infrastructure Security Agency CISA
H
Help Net Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
Hacker News - Newest:
Hacker News - Newest: "LLM"
NISL@THU
NISL@THU
J
Java Code Geeks
H
Hackread – Cybersecurity News, Data Breaches, AI and More
SecWiki News
SecWiki News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Project Zero
Project Zero
T
The Exploit Database - CXSecurity.com
TaoSecurity Blog
TaoSecurity Blog
A
Arctic Wolf
Martin Fowler
Martin Fowler
T
Threat Research - Cisco Blogs
N
News | PayPal Newsroom

博客园 - 牛奶哥

C#点滴 - 深拷贝与浅拷贝 C#点滴 - 抽象类与接口区别 C#点滴 - ?与?? C#点滴 - 值类型与引用类型 C#点滴 - 类型转换 C#点滴 - 关于String C#点滴 – 内建基本类型 C#点滴 – CLR, CTS…等等基本概念 SharePoint 2010 学习资料 初学SilverLight - (3)简单布局 初学SilverLight - (2)第一个SilverLight程序 初学SilverLight - (1)开发环境准备 WCF热带鱼书学习手记 - Security (1) 概述 关于在SharePoint中管理大文件的一些想法 WCF热带鱼书学习手记 - Service Contract Overload WCF热带鱼书学习手记 - metadata WCF热带鱼书学习手记 - endpoint - 牛奶哥 WCF热带鱼书学习手记 - ABC WCF热带鱼书学习手记 - Host Type - 牛奶哥
WCF热带鱼书学习手记 - client coding
牛奶哥 · 2009-12-23 · via 博客园 - 牛奶哥

客户调用WCF service基本上有2种方式,当然啦,都是需要编程地……

1. 通过Proxy

一般来说我们通过SvcUtil.exe来获取WCF服务的元数据,进而生成客户端可直接调用的代理类。一般语法如下:

  svcutil.exe http://localhost:9000/MyService/MyService.svc /out Proxy.cs

  svcutil.exe http://localhost:9001/MEX /out Proxy.cs

对于服务端如下的代码,客户端代理类会生成相应的调用类。

服务端:

[ServiceContract(Namespace="MyNamespace")]
interface IMyContract
{
    [OperationContract]
    void MyMethod();
}
class MyService : IMyContract
{
    public void MyMethod()
    {
        ....
    }
}

客户端代理类:

[ServiceContract(Namespace="MyNamespace")]
interface IMyContract
{
    [OperationContract(Action="MyNamespace/IMyContract/MyMethod", 
                       ReplyAction="MyNamespace/IMyContract/MyMethodResponse")]
    void MyMethod();
}
public partial class MyContractClient : ClientBase<IMyContract>, IMyContract
{
    public MyContractClient()
    {}
    public MyContractClient(string endpointName) : base(endpointName)
    {}
    public MyContractClient(Binding binding, EndpointAddress remoteAddress) : 
        base(binding, remoteAddress)
    {}
    public void MyMethod()
    {
        Channel.MyMethod();
    }
}

虽然是自动生成的代码,我们稍微看一下也是很有必要的。Proxy同样会生成IMyContract接口提供给客户端掉用。在理论上,我们可以通过这个和服务端定义相同的接口做到透明的调用服务公开的方法。这样做的基础在于,WCF客户端代理类的实际操作类实现了IMyContract类,同时在实现类封装了WCF客户端-服务端通信的所有细节。程序员不需要再显示的创建那些创建连接,设置连接,打开连接,调用方法这种东西啦。就跟写服务端代码一样,直接以IMyContract引用调用服务端方法。这个也就是同志们经常听到的“基于接口编程”的好处。

在调用代理类之前呢,还需要配置客户端WCF信息,这些东西因为是可能发生变化的部分,所以不可能固化在代理类里面,所以写在配置文件里面比较合适,反正也比较简单,基本上直接从服务端直接copy过来,然后修改一下就OK!

<system.serviceModel>
      <client name="MyNamespace.MyService">
          <endpoint contract = "MyNamespace.IMyContract"
                        binding  = "wsHttpBinding"
                        address  = "http://localhost:8000/MyService" 
          />
      </client >
</system.serviceModel>

然后就可以创建代理类实例了:

MyContractClient proxy = new MyContractClient(); //如果配置了多个endpoint,需要指定endpoint名字
proxy.MyMethod();
proxy.Close();

不过我更喜欢下面的写法,看起来就和写服务端代码一样了:

IMyContract myService = new MyContractClient(); 
myService .MyMethod();
myService .Close();

我们看MyContractClient(Binding binding, EndpointAddress remoteAddress)的构造函数,可以知道,除了可以通过配置文件设置endpoint信息,也能以变成的方式来搞定。不过相对前一种方法,这更像是hard coding,不推荐使用。知道有这种方法就行了。

2. 通过Channel

代理类有个不好的地方,当服务端契约发生变化的时候需要重新生成代理,看起来不是什么大问题,不过我在开发过程中确实遇到过类似的异常指出服务端与客户端类定义不匹配。。。不需要生成代理类的话,使用ChannelFactory是非常灵活的。这里不多说细节,给出代码先,使用起来是比较简单的。

同样的,在配置client endpoint好以后:

ChannelFactory<IMyContract> factory = new ChannelFactory<IMyContract>();
IMyContract proxy = factory.CreateChannel();
using(proxy as IDisposable)
{
    proxy.MyMethod();
}

如果没有配置endpoint的话,编程方式搞定就行:

Binding binding  = new NetTcpBinding();
EndpointAddress address = new EndpointAddress("net.tcp://localhost:9000");
IMyContract proxy = ChannelFactory<IMyContract>.CreateChannel(binding, address);
using(proxy as IDisposable)
{
    proxy.MyMethod();
}

其实基本上一样吧,因为看上面用proxy的例子,最终调用的也是一个channel...