WCF - Session 剖析
WCF中的Session
WCF是MS基于SOA建立的一套在分布式环境中各个相对独立系统进行通信的构架,实现了最新的基于WS-*规范。按照SOA的原则,相对独自的业务逻辑以service的形式封装,调用者通过Messaging的方式调用Service。对于承载着某个业务功能的实现的Service应该具有上下文无关性,也就是说个构成Service的operation不应该绑定到具体的调用上下文。因为SOA的一个最大的目标就是尽可能地实现重用,只有具有上下文无关性,Service才能实现最大限度的重用。WCF中Session属于Service Contract的范畴,是一个相对抽象的概念,并在Service Contract定义中通过SessionModel参数来实现。Session的创建和结束都有来自Client端的调用来实现。
如何实现和维护Session?
Client不能和Service进行直接交互,只能通过客户端创建的Proxy来间接地实现和service的交互,WCF在创建具体的Service Instance时会构建相关的Instance Context。我们可以制定Service的Instance context model。不同的Instance Context Mode体现为Proxy、Service 调用和Service Instance之间的对应关系,Instance Context Mode决定着不同的Session表现。在WCF中,支持以下3中不同类型的Instance Context Mode:
-
PerCall:WCF为每个Serivce调用创建 一个Service Instance,调用完成后回收该Instance。
-
PerSession:在Session期间的所有Service调用绑定到某一个Service Instance,Session被终止后,Service Instance被回收。
-
Singleton:为具体的Service type进行Host的时候,与之对应的Service Instance就被创建出来,此后所有的Service调用都被关联到该Instance。
PerCall
1 //IService
2 [ServiceContract]
3 public interface ICalculatorService
4 {
5 [OperationContract(IsOneWay = true)]
6 void PerCall(double x, double y);
7 [OperationContract]
8 double PerSession(double x, double y);
9 [OperationContract]
10 double Singleton(double x, double y);
11
16 }
17 //Service
18 public class CalculatorService : ICalculatorService
19 {
20 #region Constructor
21 public CalculatorService()
22 {
23 Console.WriteLine("Create Service Instance:Current session ID is: {0}", OperationContext.Current.SessionId);
24 }
25 #endregion
26
27 #region Destructor
28 ~CalculatorService()
29 {
30 Console.WriteLine("Destory Service Instance:Current session ID is: {0}", OperationContext.Current.SessionId);
31 }
32 #endregion
33
34 #region Result
35 private double _result;
36 public double Result
37 {
38 get
39 {
40 return _result;
41 }
42 }
43 #endregion
44
45 #region ICalculator Members
46
47 public void PerCall(double x, double y)
48 {
49 _result += x + y;
50 Console.WriteLine("PerCall:Current session ID is: {0}", OperationContext.Current.SessionId);
51 Console.WriteLine("Current result is {0}", _result.ToString());
52 }
53
54 public double PerSession(double x, double y)
55 {
56 _result += x + y;
57 Console.WriteLine("PerSession:Current session ID is: {0}", OperationContext.Current.SessionId);
58 Console.WriteLine("Current result is {0}", _result.ToString());
59 return _result;
60 }
61
62 public double Singleton(double x, double y)
63 {
64 _result += x + y;
65 Console.WriteLine("Singleton:Current session ID is: {0}", OperationContext.Current.SessionId);
66 Console.WriteLine("Current result is {0}", _result.ToString());
67 return _result;
68 }
69
78
79 #endregion
80 }
81
82 //Host httpBasicBinding
83 using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
84 {
85 Console.Title = "WCF Service Host: Session";
86 host.Opened += delegate
87 {
88 Console.WriteLine("Calculator service has been host");
89 };
90 host.Open();
91 Console.Read();
92 }
93
94 //Client httpBasicBinding
95 Console.Title = "WCF Session: Client";
96
97 ChannelFactory<ICalculatorService> channelFactory = new ChannelFactory<ICalculatorService>("CalculatorServiceEndpoint");
98 ICalculatorService channel = channelFactory.CreateChannel();
99 try
100 {
101 channel.PerCall(1, 1);
102 Console.WriteLine("Channel PerCall 1");
103 channel.PerCall(1, 1);
104 Console.WriteLine("Channel PerCall 2");
105 }
106 catch (Exception ex)
107 {
108 Console.WriteLine("Channel Exception:" + ex.Message);
109 }
110 (channel as ICommunicationObject).Close();
111
112 ICalculatorService channel2 = channelFactory.CreateChannel();
113 try
114 {
115 channel2.PerCall(1, 1);
116 Console.WriteLine("Channel2 PerCall 1");
117 channel2.PerCall(1, 1);
118 Console.WriteLine("Channel2 PerCall 2");
119 }
120 catch (Exception ex)
121 {
122 Console.WriteLine("Channel2 Exception:" + ex.Message);
123 }
124 (channel2 as ICommunicationObject).Close();
125 Console.Read();
PerSession Demo
1 //IService
2 [ServiceContract(SessionMode = SessionMode.Required)]
3 public interface ICalculatorService
4 {
5 [OperationContract]
6 void PerCall(double x, double y);
7 [OperationContract]
8 double PerSession(double x, double y);
9 [OperationContract]
10 double Singleton(double x, double y);
11
12 }
13
14
15 //Service
16 public class CalculatorService : ICalculatorService
17 {
18 #region Constructor
19 public CalculatorService()
20 {
21 Console.WriteLine("Create Service Instance:Current session ID is: {0}", OperationContext.Current.SessionId);
22 }
23 #endregion
24
25 #region Destructor
26 ~CalculatorService()
27 {
28 Console.WriteLine("Destory Service Instance:Current session ID is: {0}", OperationContext.Current.SessionId);
29 }
30 #endregion
31
32 #region Result
33 private double _result;
34 public double Result
35 {
36 get
37 {
38 return _result;
39 }
40 }
41 #endregion
42
43 #region ICalculator Members
44
45 public void PerCall(double x, double y)
46 {
47 _result += x + y;
48 Console.WriteLine("PerCall:Current session ID is: {0}", OperationContext.Current.SessionId);
49 Console.WriteLine("Current result is {0}", _result.ToString());
50 }
51
52 public double PerSession(double x, double y)
53 {
54 _result += x + y;
55 Console.WriteLine("PerSession:Current session ID is: {0}", OperationContext.Current.SessionId);
56 Console.WriteLine("Current result is {0}", _result.ToString());
57 return _result;
58 }
59
60 public double Singleton(double x, double y)
61 {
62 _result += x + y;
63 Console.WriteLine("Singleton:Current session ID is: {0}", OperationContext.Current.SessionId);
64 Console.WriteLine("Current result is {0}", _result.ToString());
65 return _result;
66 }
67
68 #endregion
69 }
70
71
72 //Host
73 using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
74 {
75 Console.Title = "WCF Service Host: Session";
76 host.Opened += delegate
77 {
78 Console.WriteLine("Calculator service has been host");
79 };
80 host.Open();
81 Console.Read();
82 }
83
84 //Client
85 Console.Title = "WCF Session: Client";
86
87 ChannelFactory<ICalculatorService> channelFactory = new ChannelFactory<ICalculatorService>("CalculatorServiceEndpoint")
88 ICalculatorService channel = channelFactory.CreateChannel();
89 try
90 {
91 double retValue = 0;
92 retValue = channel.PerSession(1, 1);
93 Console.WriteLine(string.Format("Channel PerCall 1,reback value is {0}",retValue.ToString()));
94 retValue = channel.PerSession(1, 1);
95 Console.WriteLine(string.Format("Channel PerCall 1,reback value is {0}", retValue.ToString()));
96 }
97 catch (Exception ex)
98 {
99 Console.WriteLine("Channel Exception:" + ex.Message);
100 }
101 (channel as ICommunicationObject).Close();
102
103 ICalculatorService channel2 = channelFactory.CreateChannel();
104 try
105 {
106 double retValue = 0;
107 retValue = channel2.PerSession(1, 1);
108 Console.WriteLine(string.Format("Channel PerCall 2,reback value is {0}", retValue.ToString()));
109 retValue = channel2.PerSession(1, 1);
110 Console.WriteLine(string.Format("Channel PerCall 2,reback value is {0}", retValue.ToString()));
111 }
112 catch (Exception ex)
113 {
114 Console.WriteLine("Channel2 Exception:" + ex.Message);
115 }
116 (channel2 as ICommunicationObject).Close();
117 Console.Read();
作者:RobertFang 出处:Http://fangrobert.cnblogs.com/ 欢迎转载,请转载的文章页面明显位置给出原文链接。 |