5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005-2006 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
30 using System.Collections.ObjectModel;
32 using System.ServiceModel.Channels;
33 using System.ServiceModel.Configuration;
34 using System.ServiceModel.Description;
35 using System.ServiceModel.Dispatcher;
36 using System.ServiceModel.Security;
37 using System.Reflection;
38 using System.Threading;
40 namespace System.ServiceModel
42 public abstract partial class ServiceHostBase
43 : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable
45 // It is used for mapping a ServiceHostBase to HttpChannelListener precisely.
46 internal static ServiceHostBase CurrentServiceHostHack;
48 ServiceCredentials credentials;
49 ServiceDescription description;
50 UriSchemeKeyedCollection base_addresses;
51 TimeSpan open_timeout, close_timeout, instance_idle_timeout;
52 List<InstanceContext> contexts;
53 ReadOnlyCollection<InstanceContext> exposed_contexts;
54 ChannelDispatcherCollection channel_dispatchers;
55 IDictionary<string,ContractDescription> contracts;
56 int flow_limit = int.MaxValue;
57 IExtensionCollection<ServiceHostBase> extensions;
59 protected ServiceHostBase ()
61 open_timeout = DefaultOpenTimeout;
62 close_timeout = DefaultCloseTimeout;
64 credentials = new ServiceCredentials ();
65 contexts = new List<InstanceContext> ();
66 exposed_contexts = new ReadOnlyCollection<InstanceContext> (contexts);
67 channel_dispatchers = new ChannelDispatcherCollection (this);
70 public event EventHandler<UnknownMessageReceivedEventArgs>
71 UnknownMessageReceived;
73 internal void OnUnknownMessageReceived (Message message)
75 if (UnknownMessageReceived != null)
76 UnknownMessageReceived (this, new UnknownMessageReceivedEventArgs (message));
78 // FIXME: better be logged
79 throw new EndpointNotFoundException (String.Format ("The request message has the target '{0}' with action '{1}' which is not reachable in this service contract", message.Headers.To, message.Headers.Action));
82 public ReadOnlyCollection<Uri> BaseAddresses {
84 if (base_addresses == null)
85 base_addresses = new UriSchemeKeyedCollection ();
86 return new ReadOnlyCollection<Uri> (base_addresses.InternalItems);
90 internal Uri CreateUri (string scheme, Uri relativeUri)
92 Uri baseUri = base_addresses.Contains (scheme) ? base_addresses [scheme] : null;
94 if (relativeUri == null)
96 if (relativeUri.IsAbsoluteUri)
100 var s = relativeUri.ToString ();
103 var l = baseUri.LocalPath;
104 var r = relativeUri.ToString ();
106 if (l.Length > 0 && l [l.Length - 1] != '/' && r [0] != '/')
107 return new Uri (String.Concat (baseUri.ToString (), "/", r));
109 return new Uri (String.Concat (baseUri.ToString (), r));
112 public ChannelDispatcherCollection ChannelDispatchers {
113 get { return channel_dispatchers; }
116 public ServiceAuthorizationBehavior Authorization {
121 public ServiceCredentials Credentials {
122 get { return credentials; }
125 public ServiceDescription Description {
126 get { return description; }
129 protected internal IDictionary<string,ContractDescription> ImplementedContracts {
130 get { return contracts; }
133 public IExtensionCollection<ServiceHostBase> Extensions {
135 if (extensions == null)
136 extensions = new ExtensionCollection<ServiceHostBase> (this);
141 protected internal override TimeSpan DefaultCloseTimeout {
142 get { return DefaultCommunicationTimeouts.Instance.CloseTimeout; }
145 protected internal override TimeSpan DefaultOpenTimeout {
146 get { return DefaultCommunicationTimeouts.Instance.OpenTimeout; }
149 public TimeSpan CloseTimeout {
150 get { return close_timeout; }
151 set { close_timeout = value; }
154 public TimeSpan OpenTimeout {
155 get { return open_timeout; }
156 set { open_timeout = value; }
159 public int ManualFlowControlLimit {
160 get { return flow_limit; }
161 set { flow_limit = value; }
164 protected void AddBaseAddress (Uri baseAddress)
166 if (base_addresses == null)
167 throw new InvalidOperationException ("Base addresses must be added before the service description is initialized");
168 base_addresses.Add (baseAddress);
171 public ServiceEndpoint AddServiceEndpoint (
172 string implementedContract, Binding binding, string address)
174 return AddServiceEndpoint (implementedContract,
176 new Uri (address, UriKind.RelativeOrAbsolute));
179 public ServiceEndpoint AddServiceEndpoint (
180 string implementedContract, Binding binding,
181 string address, Uri listenUri)
183 Uri uri = new Uri (address, UriKind.RelativeOrAbsolute);
184 return AddServiceEndpoint (
185 implementedContract, binding, uri, listenUri);
188 public ServiceEndpoint AddServiceEndpoint (
189 string implementedContract, Binding binding,
192 return AddServiceEndpoint (implementedContract, binding, address, null);
195 public ServiceEndpoint AddServiceEndpoint (
196 string implementedContract, Binding binding,
197 Uri address, Uri listenUri)
199 EndpointAddress ea = new EndpointAddress (BuildAbsoluteUri (address, binding));
200 ContractDescription cd = GetContract (implementedContract, binding.Namespace == "http://schemas.microsoft.com/ws/2005/02/mex/bindings");
202 throw new InvalidOperationException (String.Format ("Contract '{0}' was not found in the implemented contracts in this service host.", implementedContract));
203 return AddServiceEndpointCore (cd, binding, ea, listenUri);
207 public virtual void AddServiceEndpoint (ServiceEndpoint endpoint)
209 if (endpoint == null)
210 throw new ArgumentNullException ("endpoint");
212 ThrowIfDisposedOrImmutable ();
214 if (endpoint.Address == null)
215 throw new ArgumentException ("Address on the argument endpoint is null");
216 if (endpoint.Contract == null)
217 throw new ArgumentException ("Contract on the argument endpoint is null");
218 if (endpoint.Binding == null)
219 throw new ArgumentException ("Binding on the argument endpoint is null");
221 if (!ImplementedContracts.Values.Any (cd => cd.ContractType == endpoint.Contract.ContractType) &&
222 endpoint.Binding.Namespace != "http://schemas.microsoft.com/ws/2005/02/mex/bindings") // special case
223 throw new InvalidOperationException (String.Format ("Contract '{0}' is not implemented in this service '{1}'", endpoint.Contract.Name, Description.Name));
225 Description.Endpoints.Add (endpoint);
229 Type PopulateType (string typeName)
231 Type type = Type.GetType (typeName);
234 foreach (ContractDescription cd in ImplementedContracts.Values) {
235 type = cd.ContractType.Assembly.GetType (typeName);
242 ContractDescription mex_contract, help_page_contract;
244 ContractDescription GetContract (string name, bool mexBinding)
246 // FIXME: not sure if they should really be special cases.
248 case "IHttpGetHelpPageAndMetadataContract":
249 if (help_page_contract == null)
250 help_page_contract = ContractDescription.GetContract (typeof (IHttpGetHelpPageAndMetadataContract));
251 return help_page_contract;
252 case "IMetadataExchange":
253 // this is certainly looking special (or we may
254 // be missing something around ServiceMetadataExtension).
255 // It seems .NET WCF has some "infrastructure"
256 // endpoints. .NET ServiceHost fails to Open()
257 // if it was added only IMetadataExchange
258 // endpoint (and you'll see the word
259 // "infrastructure" in the exception message).
260 if (mexBinding && Description.Behaviors.Find<ServiceMetadataBehavior> () == null)
262 if (mex_contract == null)
263 mex_contract = ContractDescription.GetContract (typeof (IMetadataExchange));
267 Type type = PopulateType (name);
271 foreach (ContractDescription cd in ImplementedContracts.Values) {
272 // This check is a negative side effect of the above match-by-name design.
273 if (cd.ContractType == typeof (IMetadataExchange))
276 if (cd.ContractType == type ||
277 cd.ContractType.IsSubclassOf (type) ||
278 type.IsInterface && cd.ContractType.GetInterface (type.FullName) == type)
284 internal Uri BuildAbsoluteUri (Uri address, Binding binding)
286 if (!address.IsAbsoluteUri) {
287 // Find a Base address with matching scheme,
288 // and build new absolute address
289 if (!base_addresses.Contains (binding.Scheme))
290 throw new InvalidOperationException (String.Format ("Could not find base address that matches Scheme {0} for endpoint {1}", binding.Scheme, binding.Name));
292 Uri baseaddr = base_addresses [binding.Scheme];
294 if (!baseaddr.AbsoluteUri.EndsWith ("/") && address.OriginalString.Length > 0) // with empty URI it should not add '/' to possible file name of the absolute URI
295 baseaddr = new Uri (baseaddr.AbsoluteUri + "/");
296 address = new Uri (baseaddr, address);
301 internal ServiceEndpoint AddServiceEndpointCore (
302 ContractDescription cd, Binding binding, EndpointAddress address, Uri listenUri)
304 if (listenUri != null)
305 listenUri = BuildAbsoluteUri (listenUri, binding);
307 foreach (ServiceEndpoint e in Description.Endpoints)
308 if (e.Contract == cd && e.Binding == binding && e.Address == address && e.ListenUri.Equals (listenUri))
310 ServiceEndpoint se = new ServiceEndpoint (cd, binding, address);
311 // FIXME: should we reject relative ListenUri?
312 se.ListenUri = listenUri ?? address.Uri;
313 Description.Endpoints.Add (se);
317 protected virtual void ApplyConfiguration ()
319 if (Description == null)
320 throw new InvalidOperationException ("ApplyConfiguration requires that the Description property be initialized. Either provide a valid ServiceDescription in the CreateDescription method or override the ApplyConfiguration method to provide an alternative implementation");
322 ServiceElement service = GetServiceElement ();
325 LoadConfigurationSection (service);
327 // simplified configuration
328 AddServiceBehaviors (String.Empty, false);
330 // TODO: consider commonBehaviors here
332 // ensure ServiceAuthorizationBehavior
333 Authorization = Description.Behaviors.Find<ServiceAuthorizationBehavior> ();
334 if (Authorization == null) {
335 Authorization = new ServiceAuthorizationBehavior ();
336 Description.Behaviors.Add (Authorization);
339 // ensure ServiceDebugBehavior
340 ServiceDebugBehavior debugBehavior = Description.Behaviors.Find<ServiceDebugBehavior> ();
341 if (debugBehavior == null) {
342 debugBehavior = new ServiceDebugBehavior ();
343 Description.Behaviors.Add (debugBehavior);
347 void AddServiceBehaviors (string configurationName, bool throwIfNotFound)
350 if (configurationName == null)
353 if (String.IsNullOrEmpty (configurationName))
356 ServiceBehaviorElement behavior = ConfigUtil.BehaviorsSection.ServiceBehaviors [configurationName];
357 if (behavior == null) {
359 throw new ArgumentException (String.Format ("Service behavior configuration '{0}' was not found", configurationName));
363 KeyedByTypeCollection<IServiceBehavior> behaviors = Description.Behaviors;
364 foreach (var bxe in behavior) {
365 IServiceBehavior b = (IServiceBehavior) bxe.CreateBehavior ();
366 if (behaviors.Contains (b.GetType ()))
372 void ApplyServiceElement (ServiceElement service)
375 HostElement host = service.Host;
376 foreach (BaseAddressElement baseAddress in host.BaseAddresses) {
377 AddBaseAddress (new Uri (baseAddress.BaseAddress));
381 AddServiceBehaviors (service.BehaviorConfiguration, true);
384 foreach (ServiceEndpointElement endpoint in service.Endpoints) {
388 var binding = String.IsNullOrEmpty (endpoint.Binding) ? null : ConfigUtil.CreateBinding (endpoint.Binding, endpoint.BindingConfiguration);
390 if (!String.IsNullOrEmpty (endpoint.Kind)) {
391 var contract = String.IsNullOrEmpty (endpoint.Contract) ? null : GetContract (endpoint.Contract, false);
392 se = ConfigUtil.ConfigureStandardEndpoint (contract, endpoint);
393 if (se.Binding == null)
394 se.Binding = binding;
395 if (se.Address == null && se.Binding != null) // standard endpoint might have empty address
396 se.Address = new EndpointAddress (CreateUri (se.Binding.Scheme, endpoint.Address));
397 if (se.Binding == null && se.Address != null) // look for protocol mapping
398 se.Binding = ConfigUtil.GetBindingByProtocolMapping (se.Address.Uri);
400 AddServiceEndpoint (se);
403 if (binding == null && endpoint.Address != null) // look for protocol mapping
404 binding = ConfigUtil.GetBindingByProtocolMapping (endpoint.Address);
405 se = AddServiceEndpoint (endpoint.Contract, binding, endpoint.Address);
408 var binding = ConfigUtil.CreateBinding (endpoint.Binding, endpoint.BindingConfiguration);
409 se = AddServiceEndpoint (endpoint.Contract, binding, endpoint.Address);
412 // endpoint behaviors
413 EndpointBehaviorElement epbehavior = ConfigUtil.BehaviorsSection.EndpointBehaviors [endpoint.BehaviorConfiguration];
414 if (epbehavior != null)
415 foreach (var bxe in epbehavior) {
416 IEndpointBehavior b = (IEndpointBehavior) bxe.CreateBehavior ();
417 se.Behaviors.Add (b);
422 private ServiceElement GetServiceElement() {
423 Type serviceType = Description.ServiceType;
424 if (serviceType == null)
427 return ConfigUtil.ServicesSection.Services [serviceType.FullName];
430 protected abstract ServiceDescription CreateDescription (
431 out IDictionary<string,ContractDescription> implementedContracts);
433 protected void InitializeDescription (UriSchemeKeyedCollection baseAddresses)
435 this.base_addresses = baseAddresses;
436 IDictionary<string,ContractDescription> retContracts;
437 description = CreateDescription (out retContracts);
438 contracts = retContracts;
440 ApplyConfiguration ();
443 protected virtual void InitializeRuntime ()
445 //First validate the description, which should call all behaviors
447 ValidateDescription ();
449 //Build all ChannelDispatchers, one dispatcher per user configured EndPoint.
450 //We must keep thet ServiceEndpoints as a seperate collection, since the user
451 //can change the collection in the description during the behaviors events.
452 ServiceEndpoint[] endPoints = new ServiceEndpoint[Description.Endpoints.Count];
453 Description.Endpoints.CopyTo (endPoints, 0);
454 var builder = new DispatcherBuilder (this);
455 foreach (ServiceEndpoint se in endPoints) {
456 var commonParams = new BindingParameterCollection ();
457 foreach (IServiceBehavior b in Description.Behaviors)
458 b.AddBindingParameters (Description, this, Description.Endpoints, commonParams);
460 var channel = builder.BuildChannelDispatcher (Description.ServiceType, se, commonParams);
461 if (!ChannelDispatchers.Contains (channel))
462 ChannelDispatchers.Add (channel);
465 //After the ChannelDispatchers are created, and attached to the service host
466 //Apply dispatching behaviors.
468 // This behavior application order is tricky: first only
469 // ServiceDebugBehavior and ServiceMetadataBehavior are
470 // applied, and then other service behaviors are applied.
471 // It is because those two behaviors adds ChannelDispatchers
472 // and any other service behaviors must be applied to
473 // those newly populated dispatchers.
474 foreach (IServiceBehavior b in Description.Behaviors)
475 if (b is ServiceMetadataBehavior || b is ServiceDebugBehavior)
476 b.ApplyDispatchBehavior (Description, this);
477 foreach (IServiceBehavior b in Description.Behaviors)
478 if (!(b is ServiceMetadataBehavior || b is ServiceDebugBehavior))
479 b.ApplyDispatchBehavior (Description, this);
481 builder.ApplyDispatchBehaviors ();
484 private void ValidateDescription ()
486 foreach (IServiceBehavior b in Description.Behaviors)
487 b.Validate (Description, this);
488 foreach (ServiceEndpoint endPoint in Description.Endpoints)
489 endPoint.Validate ();
492 // In 4.0, it seems that if there is no configured ServiceEndpoint, infer them from the service type.
493 if (Description.Endpoints.Count == 0) {
494 foreach (Type iface in Description.ServiceType.GetInterfaces ())
495 if (iface.GetCustomAttributes (typeof (ServiceContractAttribute), true).Length > 0)
496 foreach (var baddr in BaseAddresses) {
497 if (!baddr.IsAbsoluteUri)
499 var binding = ConfigUtil.GetBindingByProtocolMapping (baddr);
502 AddServiceEndpoint (iface.FullName, binding, baddr);
507 if (Description.Endpoints.FirstOrDefault (e => e.Contract != mex_contract && !e.IsSystemEndpoint) == null)
508 throw new InvalidOperationException ("The ServiceHost must have at least one application endpoint (that does not include metadata exchange endpoint) defined by either configuration, behaviors or call to AddServiceEndpoint methods.");
511 protected void LoadConfigurationSection (ServiceElement element)
513 ApplyServiceElement (element);
516 protected override sealed void OnAbort ()
518 OnCloseOrAbort (TimeSpan.Zero);
521 Action<TimeSpan> close_delegate;
522 Action<TimeSpan> open_delegate;
524 protected override sealed IAsyncResult OnBeginClose (
525 TimeSpan timeout, AsyncCallback callback, object state)
527 if (close_delegate != null)
528 close_delegate = new Action<TimeSpan> (OnClose);
529 return close_delegate.BeginInvoke (timeout, callback, state);
532 protected override sealed IAsyncResult OnBeginOpen (
533 TimeSpan timeout, AsyncCallback callback, object state)
535 if (open_delegate == null)
536 open_delegate = new Action<TimeSpan> (OnOpen);
537 return open_delegate.BeginInvoke (timeout, callback, state);
540 protected override void OnClose (TimeSpan timeout)
542 OnCloseOrAbort (timeout);
545 void OnCloseOrAbort (TimeSpan timeout)
547 DateTime start = DateTime.Now;
548 ReleasePerformanceCounters ();
549 List<ChannelDispatcherBase> l = new List<ChannelDispatcherBase> (ChannelDispatchers);
550 foreach (ChannelDispatcherBase e in l) {
552 TimeSpan ts = timeout - (DateTime.Now - start);
553 if (ts < TimeSpan.Zero)
557 } catch (Exception ex) {
558 Console.WriteLine ("ServiceHostBase failed to close the channel dispatcher:");
559 Console.WriteLine (ex);
564 protected override sealed void OnOpen (TimeSpan timeout)
566 DateTime start = DateTime.Now;
567 InitializeRuntime ();
568 for (int i = 0; i < ChannelDispatchers.Count; i++) {
569 // Skip ServiceMetadataExtension-based one. special case.
570 for (int j = i + 1; j < ChannelDispatchers.Count; j++) {
571 var cd1 = ChannelDispatchers [i];
572 var cd2 = ChannelDispatchers [j];
573 if (cd1.IsMex || cd2.IsMex)
575 // surprisingly, some ChannelDispatcherBase implementations have null Listener property.
576 if (cd1.Listener != null && cd2.Listener != null && cd1.Listener.Uri.Equals (cd2.Listener.Uri))
577 throw new InvalidOperationException ("Two or more service endpoints with different Binding instance are bound to the same listen URI.");
581 var waits = new List<ManualResetEvent> ();
582 foreach (var cd in ChannelDispatchers) {
583 var wait = new ManualResetEvent (false);
584 cd.Opened += delegate { wait.Set (); };
586 cd.Open (timeout - (DateTime.Now - start));
589 WaitHandle.WaitAll (waits.ToArray ());
592 protected override void OnEndClose (IAsyncResult result)
594 if (close_delegate == null)
595 throw new InvalidOperationException ("Async close operation has not started");
596 close_delegate.EndInvoke (result);
599 protected override sealed void OnEndOpen (IAsyncResult result)
601 if (open_delegate == null)
602 throw new InvalidOperationException ("Aync open operation has not started");
603 open_delegate.EndInvoke (result);
606 protected override void OnOpened ()
612 protected void ReleasePerformanceCounters ()
616 void IDisposable.Dispose ()
623 /// Builds ChannelDispatchers as appropriate to service the service endpoints.
625 partial class DispatcherBuilder
627 ServiceHostBase host;
629 public DispatcherBuilder (ServiceHostBase host)
634 Dictionary<Binding,ChannelDispatcher> built_dispatchers = new Dictionary<Binding,ChannelDispatcher> ();
635 Dictionary<ServiceEndpoint, EndpointDispatcher> ep_to_dispatcher_ep = new Dictionary<ServiceEndpoint, EndpointDispatcher> ();
637 internal static Action<ChannelDispatcher> ChannelDispatcherSetter;
639 internal ChannelDispatcher BuildChannelDispatcher (Type serviceType, ServiceEndpoint se, BindingParameterCollection commonParams)
641 //Let all behaviors add their binding parameters
642 AddBindingParameters (commonParams, se);
644 // See if there's an existing channel that matches this endpoint
645 var version = se.Binding.GetProperty<MessageVersion> (commonParams);
647 throw new InvalidOperationException ("At least one BindingElement in the Binding must override GetProperty method to return a MessageVersion and no prior binding element should return null instead of calling GetInnerProperty method on BindingContext.");
649 ChannelDispatcher cd = FindExistingDispatcher (se);
650 EndpointDispatcher ep;
652 ep = cd.InitializeServiceEndpoint (serviceType, se);
654 // Use the binding parameters to build the channel listener and Dispatcher.
655 lock (HttpTransportBindingElement.ListenerBuildLock) {
656 ServiceHostBase.CurrentServiceHostHack = host;
657 IChannelListener lf = BuildListener (se, commonParams);
658 cd = new ChannelDispatcher (lf, se.Binding.Name);
659 cd.MessageVersion = version;
660 if (ChannelDispatcherSetter != null) {
661 ChannelDispatcherSetter (cd);
662 ChannelDispatcherSetter = null;
664 ServiceHostBase.CurrentServiceHostHack = null;
666 ep = cd.InitializeServiceEndpoint (serviceType, se);
667 built_dispatchers.Add (se.Binding, cd);
669 ep_to_dispatcher_ep[se] = ep;
673 ChannelDispatcher FindExistingDispatcher (ServiceEndpoint se)
675 return built_dispatchers.FirstOrDefault ((KeyValuePair<Binding,ChannelDispatcher> p) => se.Binding == p.Key).Value;
678 internal void ApplyDispatchBehaviors ()
680 foreach (KeyValuePair<ServiceEndpoint, EndpointDispatcher> val in ep_to_dispatcher_ep)
681 ApplyDispatchBehavior (val.Value, val.Key);
684 private void ApplyDispatchBehavior (EndpointDispatcher ed, ServiceEndpoint endPoint)
686 foreach (IContractBehavior b in endPoint.Contract.Behaviors)
687 b.ApplyDispatchBehavior (endPoint.Contract, endPoint, ed.DispatchRuntime);
688 foreach (IEndpointBehavior b in endPoint.Behaviors)
689 b.ApplyDispatchBehavior (endPoint, ed);
690 foreach (OperationDescription operation in endPoint.Contract.Operations) {
691 if (operation.InCallbackContract)
692 continue; // irrelevant
693 foreach (IOperationBehavior b in operation.Behaviors)
694 b.ApplyDispatchBehavior (operation, ed.DispatchRuntime.Operations [operation.Name]);
699 private void AddBindingParameters (BindingParameterCollection commonParams, ServiceEndpoint endPoint) {
701 commonParams.Add (ChannelProtectionRequirements.CreateFromContract (endPoint.Contract));
703 foreach (IContractBehavior b in endPoint.Contract.Behaviors)
704 b.AddBindingParameters (endPoint.Contract, endPoint, commonParams);
705 foreach (IEndpointBehavior b in endPoint.Behaviors)
706 b.AddBindingParameters (endPoint, commonParams);
707 foreach (OperationDescription operation in endPoint.Contract.Operations) {
708 foreach (IOperationBehavior b in operation.Behaviors)
709 b.AddBindingParameters (operation, commonParams);
713 static IChannelListener BuildListener (ServiceEndpoint se,
714 BindingParameterCollection pl)
716 Binding b = se.Binding;
717 if (b.CanBuildChannelListener<IReplySessionChannel> (pl))
718 return b.BuildChannelListener<IReplySessionChannel> (se.ListenUri, "", se.ListenUriMode, pl);
719 if (b.CanBuildChannelListener<IReplyChannel> (pl))
720 return b.BuildChannelListener<IReplyChannel> (se.ListenUri, "", se.ListenUriMode, pl);
721 if (b.CanBuildChannelListener<IInputSessionChannel> (pl))
722 return b.BuildChannelListener<IInputSessionChannel> (se.ListenUri, "", se.ListenUriMode, pl);
723 if (b.CanBuildChannelListener<IInputChannel> (pl))
724 return b.BuildChannelListener<IInputChannel> (se.ListenUri, "", se.ListenUriMode, pl);
726 if (b.CanBuildChannelListener<IDuplexChannel> (pl))
727 return b.BuildChannelListener<IDuplexChannel> (se.ListenUri, "", se.ListenUriMode, pl);
728 if (b.CanBuildChannelListener<IDuplexSessionChannel> (pl))
729 return b.BuildChannelListener<IDuplexSessionChannel> (se.ListenUri, "", se.ListenUriMode, pl);
730 throw new InvalidOperationException ("None of the listener channel types is supported");