zoukankan      html  css  js  c++  java
  • 传说中的WCF(3):多个协定

    传说中的WCF(1):这东西难学吗?
    传说中的WCF(2):服务协定的那些事儿
    传说中的WCF(3):多个协定
    传说中的WCF(4):发送和接收SOAP头
    传说中的WCF(5):数据协定(a)
    传说中的WCF(6):数据协定(b)
    传说中的WCF(7):“单向”&“双向”
    传说中的WCF(8):玩转消息协定
    传说中的WCF(9):流与文件传输
    传说中的WCF(10):消息拦截与篡改
    传说中的WCF(11):会话(Session)
    传说中的WCF(12):服务器回调有啥用
    传说中的WCF(13):群聊天程序
    传说中的WCF(14):WCF也可以做聊天程序 

    近几天忙于一些事情,没有更新博客,灰常抱歉。

    我们知道,WCF服务端是先定义服务协定,其实就是一个接口,然后通过实现接口来定义服务类。那么,有一个问题,如果一个服务类同时实现N个接口(也就是有N个协定)呢?结果会如何?

    不必猜,我们还是通过实验来说明吧。

    首先,参照下面代码写好服务器端,代码中,我写了三个协定,然后一个服务类同时实现它们。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Description;

    namespace Server
    {
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            string SayHelloA();
        }

        [ServiceContract]
        public interface IService2
        {
            [OperationContract]
            string SayHelloB();
        }

        [ServiceContract]
        public interface IService3
        {
            [OperationContract]
            string SayHelloC();
        }

        /// <summary>
        /// 实现服务协定接口的服务类
        /// </summary>
        class MyService:IService1,IService2,IService3
        {
            static void Main(string[] args)
            {
                using (ServiceHost host=new ServiceHost(typeof(MyService),new Uri("http://localhost:8001/service")))
                {
                    WSHttpBinding binding = new WSHttpBinding();
                    binding.Name = "MyBinding";
                    binding.Security.Mode = SecurityMode.None;
                    host.AddServiceEndpoint(typeof(IService1), binding, "mysv1");
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    host.Description.Behaviors.Add(behavior);

                    host.Opened += (s, a) => Console.WriteLine("服务已启动。");

                    try
                    {
                        host.Open();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    Console.ReadKey();
                    host.Close();
                }
            }

            string IService1.SayHelloA()
            {
                return "你好,这是第一个服务协定。";
            }

            string IService2.SayHelloB()
            {
                return "你好,这是第二个服务协定。";
            }

            string IService3.SayHelloC()
            {
                return "你好,这是第三个服务协定。";
            }
        }
    }


     

    接着你试一下,在客户端引用服务,看看是什么样的?

    神了,这是怎么回事呢?为什么客户端引用的服务中只有第一个协定?

    还记得刚才的服务器端代码吗?请注意看我框起来的代码。

    如果你上图中能找到原因,表明你悟性不错,呵呵。

    注意我们添加终结点的时候,AddServiceEndpoint方法的第一个参数我们传了啥玩意儿进去了?是不是只有第一个服务协定的接口?

    是啊,这上好理解了,

    我们仅仅让服务类实现多个协定的接口是不够的,还要把希望对客户端公开的协定添加为终结点,对,一个协定一个终结点,不添加终结点的协定就不公开。

    好了,现在找到原因了,代码知道怎么改了。

                using (ServiceHost host=new ServiceHost(typeof(MyService),new Uri("http://localhost:8001/service")))
                {
                    WSHttpBinding binding = new WSHttpBinding();
                    binding.Name = "MyBinding";
                    binding.Security.Mode = SecurityMode.None;
                    host.AddServiceEndpoint(typeof(IService1), binding, "mysv1");
                    host.AddServiceEndpoint(typeof(IService2), binding, "mysv2");
                    host.AddServiceEndpoint(typeof(IService3), binding, "mysv3");
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    host.Description.Behaviors.Add(behavior);

                    host.Opened += (s, a) => Console.WriteLine("服务已启动。");

                    try
                    {
                        host.Open();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    Console.ReadKey();
                    host.Close();
                }


     

    看看这回达到目的了没?

    嘿,这回全有了。

    不过,注意啊,在生成的客户端代理类中,是按协定来划分的,也就是说,我有三个协定,在客户端代码中就生成了三个客户端类。

    所以,在客户端,我们应该这样调用。

        class Program
        {
            static void Main(string[] args)
            {
                WS.Service1Client client1 = new WS.Service1Client();
                Console.WriteLine(client1.SayHelloA());

                WS.Service2Client client2 = new WS.Service2Client();
                Console.WriteLine(client2.SayHelloB());

                WS.Service3Client client3 = new WS.Service3Client();
                Console.WriteLine(client3.SayHelloC());

                Console.ReadKey();
            }


    转 黄老邪

  • 相关阅读:
    SpringBoot系统列 4
    SpringBoot系统列 3
    SpringBoot系统列 2
    SpringBoot系统列 1
    Nginx+Keepalived+Tomcat高可用负载均衡,Zookeeper集群配置,Mysql(MariaDB)搭建,Redis安装,FTP配置
    Java分布式集群,使用synchronized和Redis保证Job的原子性
    Linux 公网IP和内网IP,Dubbo提供者注册到了内网IP上怎么处理!
    SpringMvc自动任务调度之task实现项目源码,@Scheduled
    SFTP工具类
    Java代码实现文件添加数字签名、验证数字签名
  • 原文地址:https://www.cnblogs.com/jcomet/p/3058441.html
Copyright © 2011-2022 走看看