• 1.WCF学习--创建简单的WCF服务


    一、基本了解WCF
      1、面向服务代表的是一种设计理念,和面向对象、面向组件一样,体现的是一种对关注点进行分解的思想,面向服务是和技术无关的

      2、WCF需要依存一个运行着的宿主进程,服务寄宿就是为服务指定一个宿主的过程,服务寄宿的目的就是开启一个进程,为WCF提供一个运行的环境,并为服务提供一个或多个终结点,使之暴露给潜在的服务消费者
      WCF采用基于终结点(Endpoint)的通信手段。终结点由地址(Address)、绑定(Binding)、契约(Contract)三要数组成
        地址:地址决定了服务的位置,解决了服务寻址的问题
        绑定:绑定实现了通讯所有细节,包括网络传输、消息编码、以及其他为实现某种功能(比如传输安全、可靠消息、事务等)对消息进行相应的处理。
        契约:契约是对服务操作的抽象,也是对消息交换及消息结构的定义

        注意:WCF中具有一系列的系统定义绑定,比如:BasicHttpBinding、WSHttpBinding和NetTcpBinding等

    二、构建简单的WCF应用

      目录结构如下:

        Service.Interface:用于定义服务契约的类库项目,引用WCF核心程序集 System.ServiceModel.dll

        Service:用于定义服务类型的类库项目,实现服务契约(Service.Interface)

        Hosting:作为服务寄宿的控制台应用

        WCF_自我寄宿:客户端,调用服务

      定义服务契约:

    /// <summary>
    /// 用于定义服务契约的地方Contract
    /// </summary>
    namespace Service.Interface
    {
        /// <summary>
        /// 当服务被添加到客户端程序时,契约接口会被生成出来,出来的名称与 ServiceContract特性里面属性name定义的名称一样
        /// </summary>
        [ServiceContract(Name ="CalculatorService",Namespace ="http://www.artech.com/")]
        public interface ICalculator
        {
            [OperationContract]
            double Add(double x, double y);
    
            [OperationContract]
            double Subtract(double x, double y);
    
            [OperationContract]
            double Multiply(double x, double y);
    
            [OperationContract]
            double Divide(double x, double y);
        }
    }

     

      使用编程方式寄宿:

    /// <summary>
    /// 使用编程方式寄宿
    /// </summary>
    public static void Programme()
    {
        //服务寄宿
        using (ServiceHost host = new ServiceHost(typeof(Service.CalculatorService)))
        {
            //添加终结点(一个基于WSHttpBinding绑定的终结点  终结点地址:http://127.0.0.1:3721/calculatorservice  服务契约的类型:ICalculator)
            host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice");
            if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
            {
                // 添加服务行为(控制服务元数据和相关信息的发布。)
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                behavior.HttpGetEnabled = true;//指定采用http-get的元数据获取方式
                behavior.HttpGetUrl = new Uri("http://127.0.0.1:3721/calculatorservice/metadata");//指定元数据发布地址,这样在服务寄宿后我们可以通过这个地址访问服务相关的元数据
                host.Description.Behaviors.Add(behavior);
            }
    
            host.Opened += delegate
            {
                Console.WriteLine("CalculatorService 启动,按任意键终止服务!");
            };
            host.Open();//开启服务
            Console.Read();
        }
    }

     

       使用配置文件寄宿

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
        </startup>
        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="metadateBehavior">
                        <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
                        <serviceMetadata httpGetEnabled="true" httpGetUrl="calculatorservice/metadata" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="metadateBehavior" name="Service.CalculatorService">
                    <endpoint address="calculatorservice" binding="wsHttpBinding"
                        name="Service.CalculatorService" contract="Service.Interface.ICalculator" />
                    <host>
                        <baseAddresses>
                            <add baseAddress="http://127.0.0.1:3721" />
                        </baseAddresses>
                    </host>
                </service>
            </services>
        </system.serviceModel>
    </configuration>
    

      

    /// <summary>
    /// 使用配置文件添加服务
    /// </summary>
    public static void Config()
    {
        using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
        {
            host.Opened += delegate
            {
                Console.WriteLine("CalculatorService 启动,按任意键终止服务!");
            };
            host.Open();//开启服务
            Console.Read();
        }
    }

     

     

     

     

      客户端调用服务:

        1、当服务被添加后,客户端进行服务调用的服务契约接口CalculatorService会被生成出来并且与ICalculator契约接口具有相同的成员且等效
        注意:这个掉用的服务契约与定义契约接口时使用ServiceContractAttribute特性的name属性设置的一样

    namespace WCF_自我寄宿.ServiceReference1 {
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
        [System.ServiceModel.ServiceContractAttribute(Namespace="http://www.artech.com/", ConfigurationName="ServiceReference1.CalculatorService")]
        public interface CalculatorService {
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Add", ReplyAction="http://www.artech.com/CalculatorService/AddResponse")]
            double Add(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Add", ReplyAction="http://www.artech.com/CalculatorService/AddResponse")]
            System.Threading.Tasks.Task<double> AddAsync(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Subtract", ReplyAction="http://www.artech.com/CalculatorService/SubtractResponse")]
            double Subtract(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Subtract", ReplyAction="http://www.artech.com/CalculatorService/SubtractResponse")]
            System.Threading.Tasks.Task<double> SubtractAsync(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Multiply", ReplyAction="http://www.artech.com/CalculatorService/MultiplyResponse")]
            double Multiply(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Multiply", ReplyAction="http://www.artech.com/CalculatorService/MultiplyResponse")]
            System.Threading.Tasks.Task<double> MultiplyAsync(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Divide", ReplyAction="http://www.artech.com/CalculatorService/DivideResponse")]
            double Divide(double x, double y);
            
            [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Divide", ReplyAction="http://www.artech.com/CalculatorService/DivideResponse")]
            System.Threading.Tasks.Task<double> DivideAsync(double x, double y);
        }
        
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
        public interface CalculatorServiceChannel : WCF_自我寄宿.ServiceReference1.CalculatorService, System.ServiceModel.IClientChannel {
        }
        
        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
        public partial class CalculatorServiceClient : System.ServiceModel.ClientBase<WCF_自我寄宿.ServiceReference1.CalculatorService>, WCF_自我寄宿.ServiceReference1.CalculatorService {
            
            public CalculatorServiceClient() {
            }
            
            public CalculatorServiceClient(string endpointConfigurationName) : 
                    base(endpointConfigurationName) {
            }
            
            public CalculatorServiceClient(string endpointConfigurationName, string remoteAddress) : 
                    base(endpointConfigurationName, remoteAddress) {
            }
            
            public CalculatorServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                    base(endpointConfigurationName, remoteAddress) {
            }
            
            public CalculatorServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                    base(binding, remoteAddress) {
            }
            
            public double Add(double x, double y) {
                return base.Channel.Add(x, y);
            }
            
            public System.Threading.Tasks.Task<double> AddAsync(double x, double y) {
                return base.Channel.AddAsync(x, y);
            }
            
            public double Subtract(double x, double y) {
                return base.Channel.Subtract(x, y);
            }
            
            public System.Threading.Tasks.Task<double> SubtractAsync(double x, double y) {
                return base.Channel.SubtractAsync(x, y);
            }
            
            public double Multiply(double x, double y) {
                return base.Channel.Multiply(x, y);
            }
            
            public System.Threading.Tasks.Task<double> MultiplyAsync(double x, double y) {
                return base.Channel.MultiplyAsync(x, y);
            }
            
            public double Divide(double x, double y) {
                return base.Channel.Divide(x, y);
            }
            
            public System.Threading.Tasks.Task<double> DivideAsync(double x, double y) {
                return base.Channel.DivideAsync(x, y);
            }
        }
    }
    View Code

        2、查看调用服务后生成的代码可以看出来其实真正被调用的是CalculatorServiceClient类
        public interface CalculatorService
        public partial class CalculatorServiceClient : System.ServiceModel.ClientBase<WCF_自我寄宿.ServiceReference1.CalculatorService>, WCF_自我寄宿.ServiceReference1.CalculatorService
        可以看到CalculatorServiceClient同样实现了契约接口并且其基类是System.ServiceModel.ClientBase<WCF_自我寄宿.ServiceReference1.CalculatorService>,
        并通过从基类继承的Channel属性的相应方法实现了4个运算操作

       

      客户端引用服务后字节调用:

    //1、直接调用
    CalculatorServiceClient client = new CalculatorServiceClient();
    Console.WriteLine(client.Add(10, 10));

      由于WCF采用基于契约的服务调用方法。
      vs在添加服务的时候会在客户端创建一个与服务等效的服务契约接口。 public interface CalculatorService
      由于服务端和客户端在同一个解决方案里面,因此可以让服务端和客户端引用相同的契约(当然这里是删除了服务引用,并且引用服务契约1Calculator)
      通过System.ServiceModel.ChannelFactory<Tchannel>直接创建服务代理对象

    using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice"))
    {
            ICalculator calculator = channelFactory.CreateChannel();
            Console.WriteLine(calculator.Add(10, 10));
    }

     

       说明:

        终结点是WCF进行通讯的唯一手段,ChannelFactory<ICalculator>本质上是通过指定的终结点创建用于进行服务调用的服务代理

        在创建channelFactory对象的时候我们指定了 地址和绑定 泛型ChannelFactory<ICalculator>指定了 契约

     

      一般我们通过在配置文件添加终结点(常用)再通过System.ServiceModel.ChannelFactory<Tchannel>直接创建服务代理对象

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
        </startup>
        <system.serviceModel>
            <client>
                <endpoint 
                    address="http://127.0.0.1:3721/calculatorservice" 
                    binding="wsHttpBinding"
                    contract="Service.Interface.ICalculator"
                    name="CalCulatorService" />
            </client>
        </system.serviceModel>
    </configuration>

    using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("CalCulatorService"))
    {
        ICalculator calculator = channelFactory.CreateChannel();
        Console.WriteLine(calculator.Add(10, 10));
        Console.WriteLine("按任意键终止程序");
        Console.Read();
    }

     IIS寄宿:https://blog.csdn.net/heyangyi_19940703/article/details/51831094

     

     

     

  • 相关阅读:
    maven下载出错
    Android中TextView和EditView常用属性设置
    在python3.6环境下使用cxfreeze打包程序
    Python安装环境配置和多版本共存
    python manage.py migrate出错
    python使用pip安装模块出错 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None))
    类的继承
    显示一张大图两张小图思路!banner数据库设计
    微信模板
    微擎小程序第二次请求 promise
  • 原文地址:https://www.cnblogs.com/zjdbk/p/11099987.html
Copyright © 2020-2023  润新知