当前位置: 首页 > news >正文

[WCF]重载

WCF中的接口不允许有重载:

例如:

namespace WcfServiceLibrary1
{
    // NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in App.config.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        int Add(int a, int b);

        [OperationContract]
        double Add(double a, double b);

        // TODO: Add your service operations here
    }

}

namespace WcfServiceLibrary1
{
    // NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in App.config.
    public class Service1 : IService1
    {
        public int Add(int a, int b)
        {
            return a + b;
        }

        public double Add(double a, double b)
        {
            return a + b + 0.0123;  // 0.0123只是为了区别随便写的。
        }

        //More memebers
    }
}

Build这个程序不会报告错误,但是一旦启动则会在WcfSvcHost中显示Error:错误提示如下:

WcfServiceLibrary1.Service1    Error        Cannot have two operations in the same contract with the same name, methods Add and Add in type WcfServiceLibrary1.IService1 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.
[意思是:在一个契约中不能有两个重名操作(方法)……]

解决办法:

1、最简单的做法就是改名,比如一个为AddInt一个为AddDouble让它们的名字大相径庭即可……

2、使用操作契约中的昵称给它加以修改:

namespace WcfServiceLibrary1
{
    // NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in App.config.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract(Name = "AddInt")]
        int Add(int a, int b);

        [OperationContract(Name = "AddDouble")]
        double Add(double a, double b);

        // TODO: Add your service operations here
    }

}

这样在Client端以同样的方式进行处理却会抛出异常

public class CalculatorClient : ClientBase<ConsoleApplicationClient.ServiceReference.IService1>, ConsoleApplicationClient.ServiceReference.IService1
{
    public int Add1(int arg1, int arg2)
    {
        return Channel.Add(arg1, arg2);
    }

    public double Add(double arg1, double arg2)
    {
        return Channel.Add(arg1, arg2);
    }

}

image

分析原因:

旧有代码中我通过修改IService1中的方法名为Add1和Add进行测试,继而Client通过获取可以使用,但是现在我修改WcfServiceLibrary1后,Client并未获取最新的更新,而是直接将旧有Client代码修改为Add和Add,因此依照旧有的Client代码,会抛出以上异常,因此VS中我们需要重新启动我们的WcfSvcHost进程,然后再更新Client的引用。

Update

右键ServiceReference中的具体服务名,“Update Service Reference”后即可。

再次编译后则会有新的提示(未实现接口),将代码修改为:

//public int Add(int arg1, int arg2)
//{
//    return Channel.Add(arg1, arg2);
//}

//public double Add(double arg1, double arg2)
//{
//    return Channel.Add(arg1, arg2);
//}

public int AddInt(int arg1, int arg2)
{
    return Channel.AddInt(arg1, arg2);
}

public double AddDouble(double arg1, double arg2)
{
    return Channel.AddDouble(arg1, arg2);
}

修改后的代码要求按照修改的昵称对现有参数进行命名。

但是assume这是一个已经拥有很大Client logical的程序呢,我们改变interface的结果将导致整个程序无法编译正如:

Console.WriteLine("Int calculate = {0}", calculator.Add1(2, 3));
Console.WriteLine("Double calculate = {0}",calculator.Add(2.0 , 3.1));

则需要进行变换成AddInt和AddDouble才能够重新工作,这样的结果将导致不必要的麻烦(维护成本瞬间提高,整个Client的稳定性无法估计……)

How to do now?

我们最理想的就是改变我们的Proxy,让它有能力实现Overloading,这将涉及到我们的architecture of wcf,在我们Add ServiceReference的同时,我们会生成一个Proxy的类,这个类其实也就是本例中写的CalculatorClient,在你的Client程序目录路径下,你可以找到Reference.cs的文件(<程序文件>\ConsoleApplicationClient\Service References\ServiceReference),或者写一个Class中调用到Channel.×××的时候,右键则可以找到Reference.cs文件,或者将所有隐藏文件打开,在Service References\Reference.svcmap\Reference.cs可以找到……

image

我们可以看到系统为我们自动生成的Proxy类,在这里面我们注意到

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference.IService1")]
public interface IService1 {

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/AddInt", ReplyAction="http://tempuri.org/IService1/AddIntResponse")]
int AddInt(int a, int b);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/AddDouble", ReplyAction="http://tempuri.org/IService1/AddDoubleResponse")]
double AddDouble(double a, double b);

//Other Members
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class Service1Client : System.ServiceModel.ClientBase<ConsoleApplicationClient.ServiceReference.IService1>, ConsoleApplicationClient.ServiceReference.IService1 {
//Constructors

public int AddInt(int a, int b) {
    return base.Channel.AddInt(a, b);
}

public double AddDouble(double a, double b) {
    return base.Channel.AddDouble(a, b);
}
//Other Members
}

将这些改成以下样子(对Add×××方法进行重命名,并为OperationContractAttribute添加Name参数的值,使之等于之前的方法名)

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference.IService1")]
public interface IService1 {

    [System.ServiceModel.OperationContractAttribute(Name = "AddInt", Action = "http://tempuri.org/IService1/AddInt", ReplyAction = "http://tempuri.org/IService1/AddIntResponse")]
    int Add(int a, int b);
    [System.ServiceModel.OperationContractAttribute(Name = "AddDouble", Action="http://tempuri.org/IService1/AddDouble", ReplyAction="http://tempuri.org/IService1/AddDoubleResponse")]
    double Add(double a, double b);
//Other Members
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class Service1Client : System.ServiceModel.ClientBase<ConsoleApplicationClient.ServiceReference.IService1>, ConsoleApplicationClient.ServiceReference.IService1 {
//Constructors
    public int Add(int a, int b) {
        return base.Channel.Add(a, b);
    }
    public double Add(double a, double b) {
        return base.Channel.Add(a, b);
    }
//Other Members
}

之后再将所有的调用替换为修改后的重载方法即可完成重载的工作……

class Program
{
    static void Main(string[] args)
    {
        CalculatorClient calculator = new CalculatorClient();
        Console.WriteLine("Int calculate = {0}", calculator.Add(2, 3));
        Console.WriteLine("Double calculate = {0}",calculator.Add(2.0 , 3.1));
        calculator.Close();
    }
}

相关文章:

  • [python] 之 函数简介
  • [转]SharePoint升级后错误,解决方案
  • RMQ算法模板
  • 自己复制粘贴出来的第一个java小程序
  • 深入浅出JVM
  • C#3.0介绍
  • CSS菜单横竖布局要点
  • XmlReader 读取器读取内存流 MemoryStream 的注意事项
  • Oracle推导参数Derived Parameter介绍
  • [转]如何进行软件需求分析
  • 虚拟机克隆后找不到eth0
  • 通过adgjmptw看产品设计的易用性
  • es6 module模块
  • Linux下流媒体服务器的搭建(HelixServer)
  • iOS-图文表并茂,手把手教你GCD
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • JavaScript-如何实现克隆(clone)函数
  • [笔记] php常见简单功能及函数
  • 【译】理解JavaScript:new 关键字
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • emacs初体验
  • IP路由与转发
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • leetcode讲解--894. All Possible Full Binary Trees
  • Otto开发初探——微服务依赖管理新利器
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • Shell编程
  • Vue UI框架库开发介绍
  • 不上全站https的网站你们就等着被恶心死吧
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 回顾 Swift 多平台移植进度 #2
  • 前端性能优化——回流与重绘
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 一起参Ember.js讨论、问答社区。
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (C语言)共用体union的用法举例
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)Controller接口控制器详解(三)
  • (四)模仿学习-完成后台管理页面查询
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • ..回顾17,展望18
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET HttpWebRequest、WebClient、HttpClient
  • .NET开发人员必知的八个网站
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • .NET中使用Protobuffer 实现序列化和反序列化
  • .php文件都打不开,打不开php文件怎么办
  • @Conditional注解详解