2 using System
.Collections
.ObjectModel
;
3 using System
.ServiceModel
;
4 using System
.ServiceModel
.Channels
;
5 using System
.ServiceModel
.Description
;
6 using System
.ServiceModel
.Dispatcher
;
8 namespace Microsoft
.ServiceModel
.Samples
10 // This class contains the implementation for the attribute
11 // used to add pooling behavior to the service instance.
12 public sealed class ObjectPoolingAttribute
: Attribute
, IServiceBehavior
14 const int defaultMaxPoolSize
= 32;
15 const int defaultMinPoolSize
= 0;
16 int maxPoolSize
= defaultMaxPoolSize
;
17 int minPoolSize
= defaultMinPoolSize
;
19 // If the service does not already have a ServiceThrottlingBehavior, we will create
20 // one and forward all IServiceBehavior calls to it. This is used to implement
22 ServiceThrottlingBehavior throttlingBehavior
= null;
24 // Gets or sets the maximum number of objects that can be created in the pool
25 public int MaxPoolSize
27 get { return maxPoolSize; }
32 throw new ArgumentException(ResourceHelper
.GetString("ExNegativePoolSize"));
35 this.maxPoolSize
= value;
39 // Gets or sets the minimum number of objects that can be created in the pool
40 public int MinPoolSize
42 get { return minPoolSize; }
47 throw new ArgumentException(ResourceHelper
.GetString("ExNegativePoolSize"));
50 this.minPoolSize
= value;
54 #region IServiceBehavior Members
56 void IServiceBehavior
.AddBindingParameters(ServiceDescription description
, ServiceHostBase serviceHostBase
, Collection
<ServiceEndpoint
> endpoints
, BindingParameterCollection parameters
)
58 // Forward the call if we created a ServiceThrottlingBehavior.
59 if (this.throttlingBehavior
!= null)
61 ((IServiceBehavior
)this.throttlingBehavior
).AddBindingParameters(description
, serviceHostBase
, endpoints
, parameters
);
65 void IServiceBehavior
.ApplyDispatchBehavior(ServiceDescription description
, ServiceHostBase serviceHostBase
)
67 // Create an instance of the ObjectPoolInstanceProvider.
68 ObjectPoolingInstanceProvider instanceProvider
= new ObjectPoolingInstanceProvider(description
.ServiceType
,
71 // Forward the call if we created a ServiceThrottlingBehavior.
72 if (this.throttlingBehavior
!= null)
74 ((IServiceBehavior
)this.throttlingBehavior
).ApplyDispatchBehavior(description
, serviceHostBase
);
77 // In case there was already a ServiceThrottlingBehavior (this.throttlingBehavior==null),
78 // it should have initialized a single ServiceThrottle on all ChannelDispatchers. As
79 // we loop through the ChannelDispatchers, we verify that and modify the ServiceThrottle
80 // to guard MaxPoolSize.
81 ServiceThrottle throttle
= null;
83 foreach (ChannelDispatcherBase cdb
in serviceHostBase
.ChannelDispatchers
)
85 ChannelDispatcher cd
= cdb
as ChannelDispatcher
;
88 // Make sure there is exactly one throttle used by all endpoints.
89 // If there were others, we could not enforce MaxPoolSize.
90 if ((this.throttlingBehavior
== null) && (this.maxPoolSize
!= Int32
.MaxValue
))
94 throttle
= cd
.ServiceThrottle
;
96 if (cd
.ServiceThrottle
== null)
98 throw new InvalidOperationException(ResourceHelper
.GetString("ExNullThrottle"));
100 if (throttle
!= cd
.ServiceThrottle
)
102 throw new InvalidOperationException(ResourceHelper
.GetString("ExDifferentThrottle"));
106 foreach (EndpointDispatcher ed
in cd
.Endpoints
)
108 // Assign it to DispatchBehavior in each endpoint.
109 ed
.DispatchRuntime
.InstanceProvider
= instanceProvider
;
114 // Set the MaxConcurrentInstances to limit the number of items that will
115 // ever be requested from the pool.
116 if ((throttle
!= null) && (throttle
.MaxConcurrentInstances
> this.maxPoolSize
))
118 throttle
.MaxConcurrentInstances
= this.maxPoolSize
;
122 void IServiceBehavior
.Validate(ServiceDescription description
, ServiceHostBase serviceHostBase
)
124 if (this.maxPoolSize
< this.minPoolSize
)
126 throw new InvalidOperationException(ResourceHelper
.GetString("ExMinLargerThanMax"));
129 // throw if the instance context mode is Single
130 ServiceBehaviorAttribute serviceBehavior
= description
.Behaviors
.Find
<ServiceBehaviorAttribute
>();
132 if (serviceBehavior
!= null &&
133 serviceBehavior
.InstanceContextMode
== InstanceContextMode
.Single
)
135 throw new InvalidOperationException(ResourceHelper
.GetString("ExInvalidContext"));
138 // We need ServiceThrottlingBehavior to run before us, because it properly
139 // initializes the ServiceThrottle property of the endpoints. If there is
140 // no ServiceThrottlingBehavior, we will create one and run it ourselves.
141 // If there is one, we validate that it comes before us.
142 int throttlingIndex
= this.GetBehaviorIndex(description
, typeof(ServiceThrottlingBehavior
));
143 if (throttlingIndex
== -1)
145 this.throttlingBehavior
= new ServiceThrottlingBehavior();
146 this.throttlingBehavior
.MaxConcurrentInstances
= this.MaxPoolSize
;
148 // Forward the call if we created a ServiceThrottlingBehavior.
149 ((IServiceBehavior
)this.throttlingBehavior
).Validate(description
, serviceHostBase
);
153 int poolingIndex
= this.GetBehaviorIndex(description
, typeof(ObjectPoolingAttribute
));
154 if (poolingIndex
< throttlingIndex
)
156 throw new InvalidOperationException(ResourceHelper
.GetString("ExThrottleBeforePool"));
163 int GetBehaviorIndex(ServiceDescription description
, Type behaviorType
)
165 for (int i
=0; i
<description
.Behaviors
.Count
; i
++)
167 if (behaviorType
.IsInstanceOfType(description
.Behaviors
[i
]))