added samples
[windows-sources.git] / sdk / samples / WCFSamples / TechnologySamples / Extensibility / Instancing / Pooling / CS / extensions / ObjectPoolBehaviorAttribute.cs
blobbe564fc00600247050dd56a7b593c1942619bd14
1 using System;
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
21 // MaxPoolSize.
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; }
28 set
30 if (value < 0)
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; }
43 set
45 if (value < 0)
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,
69 minPoolSize);
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;
86 if (cd != null)
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))
92 if (throttle == null)
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);
151 else
153 int poolingIndex = this.GetBehaviorIndex(description, typeof(ObjectPoolingAttribute));
154 if (poolingIndex < throttlingIndex)
156 throw new InvalidOperationException(ResourceHelper.GetString("ExThrottleBeforePool"));
161 #endregion
163 int GetBehaviorIndex(ServiceDescription description, Type behaviorType)
165 for (int i=0; i<description.Behaviors.Count; i++)
167 if (behaviorType.IsInstanceOfType(description.Behaviors[i]))
169 return i;
173 return -1;