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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//引入命名空间:using System.ServiceModel;<br> <br>   [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() //不被放入服务
      {
          //业务实现
      }<br>    }

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[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,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//封装了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();
 
    }
 
 
}

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

   调用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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>类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[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 @   objnet  阅读(168)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示