读书笔记摘要- 第一个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();

            }

        }
    }

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

 

posted @ 2020-03-31 21:26  objnet  阅读(168)  评论(0编辑  收藏  举报