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

推荐订阅源

Google Online Security Blog
Google Online Security Blog
S
Security @ Cisco Blogs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
人人都是产品经理
人人都是产品经理
The Hacker News
The Hacker News
W
WeLiveSecurity
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
博客园 - 司徒正美
雷峰网
雷峰网
L
LINUX DO - 最新话题
博客园 - 叶小钗
云风的 BLOG
云风的 BLOG
The Last Watchdog
The Last Watchdog
V2EX - 技术
V2EX - 技术
S
Security Affairs
有赞技术团队
有赞技术团队
月光博客
月光博客
T
Threatpost
T
Tor Project blog
O
OpenAI News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
V2EX
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
博客园 - 三生石上(FineUI控件)
D
Docker
AWS News Blog
AWS News Blog
AI
AI
P
Proofpoint News Feed
K
Kaspersky official blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
Darknet – Hacking Tools, Hacker News & Cyber Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Securelist
F
Fortinet All Blogs
F
Full Disclosure
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
量子位
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Palo Alto Networks Blog
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
美团技术团队
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog

博客园 - 牛奶哥

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...