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

推荐订阅源

云风的 BLOG
云风的 BLOG
有赞技术团队
有赞技术团队
Simon Willison's Weblog
Simon Willison's Weblog
人人都是产品经理
人人都是产品经理
L
LINUX DO - 最新话题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
A
Arctic Wolf
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
小众软件
小众软件
Jina AI
Jina AI
The Cloudflare Blog
P
Palo Alto Networks Blog
AWS News Blog
AWS News Blog
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
Know Your Adversary
Know Your Adversary
T
Threat Research - Cisco Blogs
L
Lohrmann on Cybersecurity
NISL@THU
NISL@THU
G
GRAHAM CLULEY
Project Zero
Project Zero
博客园_首页
博客园 - 三生石上(FineUI控件)
罗磊的独立博客
Spread Privacy
Spread Privacy
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
Latest news
Latest news
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
S
Securelist
V
Vulnerabilities – Threatpost
T
The Exploit Database - CXSecurity.com
C
CERT Recently Published Vulnerability Notes
IT之家
IT之家
Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Last Watchdog
The Last Watchdog
T
Tenable Blog
宝玉的分享
宝玉的分享
S
Secure Thoughts
P
Privacy & Cybersecurity Law Blog
量子位
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Security Archives - TechRepublic
Security Archives - TechRepublic

博客园 - 牛奶哥

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热带鱼书学习手记 - client coding WCF热带鱼书学习手记 - metadata WCF热带鱼书学习手记 - endpoint - 牛奶哥 WCF热带鱼书学习手记 - ABC WCF热带鱼书学习手记 - Host Type - 牛奶哥
WCF热带鱼书学习手记 - Service Contract Overload
牛奶哥 · 2009-12-23 · via 博客园 - 牛奶哥

重载是面向对象编程里面比较常见的一个问题,如下:

interface ICalculator
{
    int Add(int a, int b);
    double Add(double a, double b);
}

通过不同的参数列表,给出不一样的函数签名。但是在WCF通过interface公开服务契约的时候,有这样一个问题。直接在这2个Add方法上添加[OperationContract]会导致异常发生。

我们来创建一个例子,服务端代码:

interface ICalculator
{
    [OperationContract]
    int Add(int a, int b);
 
    [OperationContract]
    double Add(double a, double b);
}
 
........

static void Main(string[] args)
{
    try
    {
        ServiceHost host = new ServiceHost(typeof(Calculator));
        Binding wsHttpBinding = new WSHttpBinding();
        host.AddServiceEndpoint(typeof(ICalculator), wsHttpBinding, new Uri("http://localhost:8086/Calculator/"));
        host.Open();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    Console.Read();
}

在启动self-host的时候遇到如下的异常信息:

System.InvalidOperationException: Cannot have two operations in the same contract with the same name, methods Add and Add in type Server.ICalculator violate this rule. You can change the name of one of the operations by changing the method name or by using the Name property of OperationContractAttribute.

原因在于,基于wsdl的方法是不支持重载的,方法名是唯一的标识。WCF提供了一个解决方法,就是给[OperationContract]一个name属性。

[ServiceContract]
interface ICalculator
{
    [OperationContract(Name="AddInt")]
    int Add(int a, int b);
 
    [OperationContract(Name="AddDouble")]
    double Add(double a, double b);
}

 重新启动self-host以后,异常不再出现。从客户端角度来看,如果以channel的方式调用:

static void Main(string[] args)
{
    Binding binding = new WSHttpBinding();
    EndpointAddress address = new EndpointAddress("http://localhost:8086/Calculator/");
    ICalculator proxy = ChannelFactory<ICalculator>.CreateChannel(binding, address);
    using (proxy as IDisposable)
    {
        Console.WriteLine(proxy.Add(1, 2));
        Console.WriteLine(proxy.Add(1.0, 2.0));
    }
    Console.Read();
}

因为是引用了ICalculator接口,客户端也支持了面向对象语言的重载特性。但如果使用的自动生成的proxy类,会生成类似如下的类定义:

[ServiceContract]
interface ICalculator
{
    [OperationContract]
    int AddInt(int a, int b);
 
    [OperationContract]
    double AddDouble(double a, double b);
}
 
public partial class CalculatorClient : ClientBase<ICalculator>, ICalculator
{
    public int AddInt(int a, int b)
    {
        return Channel.AddInt(a, b);
    }
 
    public int AddDouble(double a, double b)
    {
        return Channel.AddDouble(a, b);
    }
}
.....

为了让代理类也支持重载特性,可以手工的修改代理:

[ServiceContract]
interface ICalculator
{
    [OperationContract(Name="AddInt")]
    int Add(int a, int b);
 
    [OperationContract(Name="AddDouble")]
    double Add(double a, double b);
}
 
public partial class CalculatorClient : ClientBase<ICalculator>, ICalculator
{
    public int Add(int a, int b)
    {
        return Channel.Add(a, b);
    }
 
    public int Add(double a, double b)
    {
        return Channel.Add(a, b);
    }
}
.....

然后我们在调用代理类的时候,可以同使用channel一样,使用重载特性啦。。。。

CalculatorClient proxy = new CalculatorClient ();
Console.WriteLine(proxy.Add(1, 2));
Console.WriteLine(proxy.Add(1.0, 2.0));
proxy.Close();