• 读书笔记摘要- 第一个WCF程序


    1.定义一个服务契约使用ServiceContract特性:用于类或者接口亦可,且允许重复

    2.一个服务契约由一组操作服务构成,定义操作服务用OperationContract特性,只有定义了操作服务的方法才会放入氛围中如下实例:

      //引入命名空间:using System.ServiceModel;

    [ServiceContract] public interface IService { [OperationContract] void Work(); //被引入服务 [OperationContract] void Eat(); //被放入服务 void Run();//不被放入服务 } [ServiceContract] public class Service { [OperationContract] public void Work() //被放入服务 { //业务实现 } [OperationContract] public void Eat() //被放入服务 { //业务实现 } public void Run() //不被放入服务 { //业务实现 }
    }

      备注:WCF或构造一个定义的接口,并使用该接口作为服务契约的定义,所以服务契约的定义都是由接口完成的。不建议定义在类里,原因是不可重用。

        [ServiceContract]   
        interface IService   //服务的定义
        {
            [OperationContract]
            string HelloWorld(string name);//服务操作
        }
    
    
        public class Service : IService   //服务的实现
        {
           public string HelloWorld(string name) //服务操作实现
            {
                return name + "speak:HelloWorld!";//拼接字符串并返回
            }
        }
    

      注意:服务需要寄宿到每个特定的程序之后才可以被访问。

    3、服务宿主程序需要使用ServiceHost类型,当使用IIS或者WAS作为宿主程序时,IIS和WAS会主动创建ServiceHost类型对象,如果是针对于的宿主服务需要手动创建ServiceHost对象,常见的构造方法:

    /// <summary>
    /// ServiceHost构造函数
    /// </summary>
    /// <param name="serviceType">契约定义类型</param>
    /// <param name="baseAddress">基地址数组</param>
    public ServiceHost(Type serviceType, params Uri[] baseAddress);

     一个完整的服务宿主程序还需要定义服务的绑定和地址

     基于宿主程序和客户端都是运行在同一主机,所以服务选择性能最佳但不能跨越主机的NetNamedPipeBinding.该绑定使用IPC协议进行通信,可跨越应用程序域和进程。但不能跨越主机。 

    public Binding GetBinding()
        {
            return new NetNamedPipeBinding();//返回NetNamedPipeBinding对象
        }

      接下来定义服务地址:两部分组成,即基地址和可选地址,基地址包含通信协议和主机名,可选地址定义服务位置。这里用的是

    NetNamedPipeBinding绑定。所以级地震为net.pipe://localhost.可选地址为Hellword.基地址在ServiceHost对象构造时被党作为参数传入。可选地址在终结点被添加时使用,添加终结点使用
    ServiceHost的AddServiceEndpoint()方法。
    HelloWorld定义了MyServiceHost类型来封装ServiceHost,如下:
        //封装了ServiceHost和起构造过程
        public class MyServiceHost
        {
            private ServiceHost _myHost;  //ServiceHost对象
    
            public const string BaseAddress = "net.pipe://localhost";//基地址
            public const string HelloWorldServiceAddress = "HelloWorld";//可选地址
    
            //服务契约定义类型
            public static readonly Type ContractType = typeof(HelloWorldService.IService);
    
            //服务契约实现类型
            public static readonly Type ServiceType = typeof(HelloWorldService.Service);
    
            //服务只定义了一个绑定
            public static readonly Binding HelloWorldBing = new NetNamedPipeBinding();
    
            //构造ServiceHost对象
            protected void ConstructServiceHost()
            {
                //初始化ServiceHost对象
                _myHost = new ServiceHost(ServiceType,new Uri[] { new Uri(BaseAddress)});
    
                _myHost.AddServiceEndpoint(ContractType,HelloWorldBing,HelloWorldServiceAddress);
    
            }
    
            //ServiceHost只读属性
            public ServiceHost Host { get { return _myHost; } }
    
            //打开服务
            public void Open()
            {
                _myHost.Open();
    
            }
    
            //构造方法
            public MyServiceHost()
            {
                ConstructServiceHost();
    
            }
    
            //ServiceHost实现了IDisposable接口,这里调用它的Dispose()方法
            public void Dispose()
            {
                //ServiceHost显示实现了IDisposable的Dispose()方法,所以要先强制转换成IDisposable类型
                if (_myHost != null)
                    (_myHost as IDisposable).Dispose();
    
            }
    
    
        }
    

      注意:以上实例采用编程配置的方式定义服务的绑定、终结点、地址等信息。后期推荐用配置文件来配置(无需编译、直观简单)。

       调用示例:

     public class ServiceHostMainClass  //服务的宿主
        {
    
            static void Main(string[] args) //入口方法调用
            {
                //由于MyServiceHost实现了IDisposable接口,所以使用using 自动关闭
                using (MyServiceHost host=new MyServiceHost())
                {
                    host.Open();
                    Console.Read();//待客户端访问
    
                }
    
            }
    
        }
    

      4、手动创建客户端代理方式访问服务端:

          第一、导入服务元数据,服务元数据的内容包含服务提供的终结点,每个终结点的地址、绑定和契约。元数据又称元数据的交换,一般用二种方法获取,即HTTP-GET和元数据终结点方法。此处采用编码方式定义服务的契约地址和绑定。

     第二、定义访问服务的代理类型。WCF提供了ClientBase<T>来定义代理类型。泛型参数T被访问契约类型实例化,绑定和地址在ClientBase<T>的构造方法中被传入,对象构造完毕后,采用用Channel属性对服务进行调用。以下示例采用HelloWorlProxy类型用于封装ClientBase<T>类型:

    [ServiceContract]
        interface Iservice   //硬编码定义服务契约
        {
            [OperationContract]
            string HelloWorld(string name);//服务操作
        }
    
        //客户端代理类型
        public class HelloWorldProxy : ClientBase<Iservice>, Iservice
        {
            //硬编码定义绑定
            public static readonly Binding HelloWorldBinding = new NetNamedPipeBinding();
    
            //硬编码定义地址
            public static readonly EndpointAddress HelloWorldAddress = new EndpointAddress(new Uri("net.pipe://localhost/HelloWorld"));
    
            //构造方法
            public HelloWorldProxy() : base(HelloWorldBinding, HelloWorldAddress)
            {
            }
    
            public string HelloWorld(string name)
            {
    
                return Channel.HelloWorld(name);//使用Channel属性对服务进行调用
            }
    
        }
    

      定义代理类型后可在入口使用,因ClienBase<T>实现了IDisposable接口,所以要用using自动关闭:

     public class Client
        {
            static void Main(string[] args)
            {
                using (HelloWorldProxy proxy = new HelloWorldProxy())
                {
                    Console.WriteLine(  proxy.HelloWorld("WCF"));//利用代理调用服务
                    Console.Read();
    
                }
    
            }
        }

      必选先启动服务再启动客户端调用生效。

  • 相关阅读:
    mysql 之 double( totalsize, decimal)
    java8 实战--- Map merge用法
    java8 stream接口 终端操作 min,max,findFirst,findAny
    tinyint(1)详解
    表单插件——form
    表单验证插件——validate
    使用ajaxStart()和ajaxStop()方法
    使用ajaxSetup()方法设置全局Ajax默认选项
    使用ajax()方法加载服务器数据
    使用serialize()方法序列化表单元素值
  • 原文地址:https://www.cnblogs.com/professional-NET/p/12608656.html
Copyright © 2020-2023  润新知