PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/System.ServiceModel/System.ServiceModel/ServiceHostBase.cs

https://bitbucket.org/steenlund/mono-2.6.7-for-amiga
C# | 649 lines | 430 code | 78 blank | 141 comment | 81 complexity | 844a1cb065669fc0dc459954d1a486ea MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, LGPL-2.1
  1. //
  2. // ServiceHostBase.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <atsushi@ximian.com>
  6. //
  7. // Copyright (C) 2005-2006 Novell, Inc. http://www.novell.com
  8. //
  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:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  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.
  27. //
  28. using System;
  29. using System.Collections.Generic;
  30. using System.Collections.ObjectModel;
  31. using System.Linq;
  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. namespace System.ServiceModel
  39. {
  40. public abstract partial class ServiceHostBase
  41. : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable
  42. {
  43. ServiceCredentials credentials;
  44. ServiceDescription description;
  45. UriSchemeKeyedCollection base_addresses;
  46. TimeSpan open_timeout, close_timeout, instance_idle_timeout;
  47. ServiceThrottle throttle;
  48. List<InstanceContext> contexts;
  49. ReadOnlyCollection<InstanceContext> exposed_contexts;
  50. ChannelDispatcherCollection channel_dispatchers;
  51. IDictionary<string,ContractDescription> contracts;
  52. int flow_limit = int.MaxValue;
  53. IExtensionCollection<ServiceHostBase> extensions;
  54. protected ServiceHostBase ()
  55. {
  56. open_timeout = DefaultOpenTimeout;
  57. close_timeout = DefaultCloseTimeout;
  58. credentials = new ServiceCredentials ();
  59. throttle = new ServiceThrottle ();
  60. contexts = new List<InstanceContext> ();
  61. exposed_contexts = new ReadOnlyCollection<InstanceContext> (contexts);
  62. channel_dispatchers = new ChannelDispatcherCollection (this);
  63. }
  64. public event EventHandler<UnknownMessageReceivedEventArgs>
  65. UnknownMessageReceived;
  66. internal void OnUnknownMessageReceived (Message message)
  67. {
  68. if (UnknownMessageReceived != null)
  69. UnknownMessageReceived (this, new UnknownMessageReceivedEventArgs (message));
  70. else
  71. // FIXME: better be logged
  72. 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));
  73. }
  74. public ReadOnlyCollection<Uri> BaseAddresses {
  75. get {
  76. if (base_addresses == null)
  77. base_addresses = new UriSchemeKeyedCollection ();
  78. return new ReadOnlyCollection<Uri> (base_addresses.InternalItems);
  79. }
  80. }
  81. internal Uri CreateUri (string scheme, Uri relativeUri)
  82. {
  83. Uri baseUri = base_addresses.Contains (scheme) ? base_addresses [scheme] : null;
  84. if (relativeUri == null)
  85. return baseUri;
  86. if (relativeUri.IsAbsoluteUri)
  87. return relativeUri;
  88. if (baseUri == null)
  89. return null;
  90. var s = relativeUri.ToString ();
  91. if (s.Length == 0)
  92. return baseUri;
  93. var l = baseUri.LocalPath;
  94. var r = relativeUri.ToString ();
  95. if (l.Length > 0 && l [l.Length - 1] != '/' && r [0] != '/')
  96. return new Uri (String.Concat (baseUri.ToString (), "/", r));
  97. else
  98. return new Uri (String.Concat (baseUri.ToString (), r));
  99. }
  100. public ChannelDispatcherCollection ChannelDispatchers {
  101. get { return channel_dispatchers; }
  102. }
  103. public ServiceAuthorizationBehavior Authorization {
  104. get;
  105. private set;
  106. }
  107. [MonoTODO]
  108. public ServiceCredentials Credentials {
  109. get { return credentials; }
  110. }
  111. public ServiceDescription Description {
  112. get { return description; }
  113. }
  114. protected IDictionary<string,ContractDescription> ImplementedContracts {
  115. get { return contracts; }
  116. }
  117. [MonoTODO]
  118. public IExtensionCollection<ServiceHostBase> Extensions {
  119. get {
  120. if (extensions == null)
  121. extensions = new ExtensionCollection<ServiceHostBase> (this);
  122. return extensions;
  123. }
  124. }
  125. protected internal override TimeSpan DefaultCloseTimeout {
  126. get { return DefaultCommunicationTimeouts.Instance.CloseTimeout; }
  127. }
  128. protected internal override TimeSpan DefaultOpenTimeout {
  129. get { return DefaultCommunicationTimeouts.Instance.OpenTimeout; }
  130. }
  131. public TimeSpan CloseTimeout {
  132. get { return close_timeout; }
  133. set { close_timeout = value; }
  134. }
  135. public TimeSpan OpenTimeout {
  136. get { return open_timeout; }
  137. set { open_timeout = value; }
  138. }
  139. public int ManualFlowControlLimit {
  140. get { return flow_limit; }
  141. set { flow_limit = value; }
  142. }
  143. protected void AddBaseAddress (Uri baseAddress)
  144. {
  145. if (base_addresses == null)
  146. throw new InvalidOperationException ("Base addresses must be added before the service description is initialized");
  147. base_addresses.Add (baseAddress);
  148. }
  149. public ServiceEndpoint AddServiceEndpoint (
  150. string implementedContract, Binding binding, string address)
  151. {
  152. return AddServiceEndpoint (implementedContract,
  153. binding,
  154. new Uri (address, UriKind.RelativeOrAbsolute));
  155. }
  156. public ServiceEndpoint AddServiceEndpoint (
  157. string implementedContract, Binding binding,
  158. string address, Uri listenUri)
  159. {
  160. Uri uri = new Uri (address, UriKind.RelativeOrAbsolute);
  161. return AddServiceEndpoint (
  162. implementedContract, binding, uri, listenUri);
  163. }
  164. public ServiceEndpoint AddServiceEndpoint (
  165. string implementedContract, Binding binding,
  166. Uri address)
  167. {
  168. return AddServiceEndpoint (implementedContract, binding, address, address);
  169. }
  170. public ServiceEndpoint AddServiceEndpoint (
  171. string implementedContract, Binding binding,
  172. Uri address, Uri listenUri)
  173. {
  174. EndpointAddress ea = BuildEndpointAddress (address, binding);
  175. ContractDescription cd = GetContract (implementedContract, binding.Name == "MetadataExchangeHttpBinding");
  176. if (cd == null)
  177. throw new InvalidOperationException (String.Format ("Contract '{0}' was not found in the implemented contracts in this service host.", implementedContract));
  178. return AddServiceEndpointCore (cd, binding, ea, listenUri);
  179. }
  180. Type PopulateType (string typeName)
  181. {
  182. Type type = Type.GetType (typeName);
  183. if (type != null)
  184. return type;
  185. foreach (ContractDescription cd in ImplementedContracts.Values) {
  186. type = cd.ContractType.Assembly.GetType (typeName);
  187. if (type != null)
  188. return type;
  189. }
  190. return null;
  191. }
  192. ContractDescription mex_contract, help_page_contract;
  193. ContractDescription GetContract (string name, bool mexBinding)
  194. {
  195. // FIXME: not sure if they should really be special cases.
  196. switch (name) {
  197. case "IHttpGetHelpPageAndMetadataContract":
  198. if (help_page_contract == null)
  199. help_page_contract = ContractDescription.GetContract (typeof (IHttpGetHelpPageAndMetadataContract));
  200. return help_page_contract;
  201. case "IMetadataExchange":
  202. // this is certainly looking special (or we may
  203. // be missing something around ServiceMetadataExtension).
  204. // It seems .NET WCF has some "infrastructure"
  205. // endpoints. .NET ServiceHost fails to Open()
  206. // if it was added only IMetadataExchange
  207. // endpoint (and you'll see the word
  208. // "infrastructure" in the exception message).
  209. if (mexBinding && Description.Behaviors.Find<ServiceMetadataBehavior> () == null)
  210. break;
  211. if (mex_contract == null)
  212. mex_contract = ContractDescription.GetContract (typeof (IMetadataExchange));
  213. return mex_contract;
  214. }
  215. Type type = PopulateType (name);
  216. if (type == null)
  217. return null;
  218. foreach (ContractDescription cd in ImplementedContracts.Values) {
  219. // This check is a negative side effect of the above match-by-name design.
  220. if (cd.ContractType == typeof (IMetadataExchange))
  221. continue;
  222. if (cd.ContractType == type ||
  223. cd.ContractType.IsSubclassOf (type) ||
  224. type.IsInterface && cd.ContractType.GetInterface (type.FullName) == type)
  225. return cd;
  226. }
  227. return null;
  228. }
  229. internal EndpointAddress BuildEndpointAddress (Uri address, Binding binding)
  230. {
  231. if (!address.IsAbsoluteUri) {
  232. // Find a Base address with matching scheme,
  233. // and build new absolute address
  234. if (!base_addresses.Contains (binding.Scheme))
  235. throw new InvalidOperationException (String.Format ("Could not find base address that matches Scheme {0} for endpoint {1}", binding.Scheme, binding.Name));
  236. Uri baseaddr = base_addresses [binding.Scheme];
  237. if (!baseaddr.AbsoluteUri.EndsWith ("/") && address.OriginalString.Length > 0) // with empty URI it should not add '/' to possible file name of the absolute URI
  238. baseaddr = new Uri (baseaddr.AbsoluteUri + "/");
  239. address = new Uri (baseaddr, address);
  240. }
  241. return new EndpointAddress (address);
  242. }
  243. internal ServiceEndpoint AddServiceEndpointCore (
  244. ContractDescription cd, Binding binding, EndpointAddress address, Uri listenUri)
  245. {
  246. foreach (ServiceEndpoint e in Description.Endpoints)
  247. if (e.Contract == cd)
  248. return e;
  249. ServiceEndpoint se = new ServiceEndpoint (cd, binding, address);
  250. se.ListenUri = listenUri.IsAbsoluteUri ? listenUri : new Uri (address.Uri, listenUri);
  251. Description.Endpoints.Add (se);
  252. return se;
  253. }
  254. [MonoTODO]
  255. protected virtual void ApplyConfiguration ()
  256. {
  257. if (Description == null)
  258. 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");
  259. ServiceElement service = GetServiceElement ();
  260. //TODO: Should we call here LoadServiceElement ?
  261. if (service != null) {
  262. //base addresses
  263. HostElement host = service.Host;
  264. foreach (BaseAddressElement baseAddress in host.BaseAddresses) {
  265. AddBaseAddress (new Uri (baseAddress.BaseAddress));
  266. }
  267. // behaviors
  268. // TODO: use EvaluationContext of ServiceElement.
  269. ServiceBehaviorElement behavior = ConfigUtil.BehaviorsSection.ServiceBehaviors [service.BehaviorConfiguration];
  270. if (behavior != null) {
  271. foreach (var bxe in behavior) {
  272. IServiceBehavior b = (IServiceBehavior) bxe.CreateBehavior ();
  273. Description.Behaviors.Add (b);
  274. }
  275. }
  276. // services
  277. foreach (ServiceEndpointElement endpoint in service.Endpoints) {
  278. // FIXME: consider BindingName as well
  279. ServiceEndpoint se = AddServiceEndpoint (
  280. endpoint.Contract,
  281. ConfigUtil.CreateBinding (endpoint.Binding, endpoint.BindingConfiguration),
  282. endpoint.Address.ToString ());
  283. // endpoint behaviors
  284. EndpointBehaviorElement epbehavior = ConfigUtil.BehaviorsSection.EndpointBehaviors [endpoint.BehaviorConfiguration];
  285. if (epbehavior != null)
  286. foreach (var bxe in epbehavior) {
  287. IEndpointBehavior b = (IEndpointBehavior) bxe.CreateBehavior ();
  288. se.Behaviors.Add (b);
  289. }
  290. }
  291. }
  292. // TODO: consider commonBehaviors here
  293. // ensure ServiceAuthorizationBehavior
  294. Authorization = Description.Behaviors.Find<ServiceAuthorizationBehavior> ();
  295. if (Authorization == null) {
  296. Authorization = new ServiceAuthorizationBehavior ();
  297. Description.Behaviors.Add (Authorization);
  298. }
  299. // ensure ServiceDebugBehavior
  300. ServiceDebugBehavior debugBehavior = Description.Behaviors.Find<ServiceDebugBehavior> ();
  301. if (debugBehavior == null) {
  302. debugBehavior = new ServiceDebugBehavior ();
  303. Description.Behaviors.Add (debugBehavior);
  304. }
  305. }
  306. private ServiceElement GetServiceElement() {
  307. Type serviceType = Description.ServiceType;
  308. if (serviceType == null)
  309. return null;
  310. return ConfigUtil.ServicesSection.Services [serviceType.FullName];
  311. }
  312. protected abstract ServiceDescription CreateDescription (
  313. out IDictionary<string,ContractDescription> implementedContracts);
  314. protected void InitializeDescription (UriSchemeKeyedCollection baseAddresses)
  315. {
  316. this.base_addresses = baseAddresses;
  317. IDictionary<string,ContractDescription> retContracts;
  318. description = CreateDescription (out retContracts);
  319. contracts = retContracts;
  320. ApplyConfiguration ();
  321. }
  322. protected virtual void InitializeRuntime ()
  323. {
  324. //First validate the description, which should call all behaviors
  325. //'Validate' method.
  326. ValidateDescription ();
  327. //Build all ChannelDispatchers, one dispatcher per user configured EndPoint.
  328. //We must keep thet ServiceEndpoints as a seperate collection, since the user
  329. //can change the collection in the description during the behaviors events.
  330. Dictionary<ServiceEndpoint, ChannelDispatcher> endPointToDispatcher = new Dictionary<ServiceEndpoint,ChannelDispatcher>();
  331. ServiceEndpoint[] endPoints = new ServiceEndpoint[Description.Endpoints.Count];
  332. Description.Endpoints.CopyTo (endPoints, 0);
  333. foreach (ServiceEndpoint se in endPoints) {
  334. var commonParams = new BindingParameterCollection ();
  335. foreach (IServiceBehavior b in Description.Behaviors)
  336. b.AddBindingParameters (Description, this, Description.Endpoints, commonParams);
  337. var channel = new DispatcherBuilder ().BuildChannelDispatcher (Description.ServiceType, se, commonParams);
  338. ChannelDispatchers.Add (channel);
  339. endPointToDispatcher[se] = channel;
  340. }
  341. //After the ChannelDispatchers are created, and attached to the service host
  342. //Apply dispatching behaviors.
  343. foreach (IServiceBehavior b in Description.Behaviors)
  344. b.ApplyDispatchBehavior (Description, this);
  345. foreach(KeyValuePair<ServiceEndpoint, ChannelDispatcher> val in endPointToDispatcher)
  346. foreach (var ed in val.Value.Endpoints)
  347. ApplyDispatchBehavior (ed, val.Key);
  348. }
  349. private void ValidateDescription ()
  350. {
  351. foreach (IServiceBehavior b in Description.Behaviors)
  352. b.Validate (Description, this);
  353. foreach (ServiceEndpoint endPoint in Description.Endpoints)
  354. endPoint.Validate ();
  355. if (Description.Endpoints.FirstOrDefault (e => e.Contract != mex_contract) == null)
  356. throw new InvalidOperationException ("The ServiceHost must have at least one application endpoint (that does not include metadata exchange contract) defined by either configuration, behaviors or call to AddServiceEndpoint methods.");
  357. }
  358. private void ApplyDispatchBehavior (EndpointDispatcher ed, ServiceEndpoint endPoint)
  359. {
  360. foreach (IContractBehavior b in endPoint.Contract.Behaviors)
  361. b.ApplyDispatchBehavior (endPoint.Contract, endPoint, ed.DispatchRuntime);
  362. foreach (IEndpointBehavior b in endPoint.Behaviors)
  363. b.ApplyDispatchBehavior (endPoint, ed);
  364. foreach (OperationDescription operation in endPoint.Contract.Operations) {
  365. foreach (IOperationBehavior b in operation.Behaviors)
  366. b.ApplyDispatchBehavior (operation, ed.DispatchRuntime.Operations [operation.Name]);
  367. }
  368. }
  369. [MonoTODO]
  370. protected void LoadConfigurationSection (ServiceElement element)
  371. {
  372. ServicesSection services = ConfigUtil.ServicesSection;
  373. }
  374. [MonoTODO]
  375. protected override sealed void OnAbort ()
  376. {
  377. }
  378. Action<TimeSpan> close_delegate;
  379. Action<TimeSpan> open_delegate;
  380. protected override sealed IAsyncResult OnBeginClose (
  381. TimeSpan timeout, AsyncCallback callback, object state)
  382. {
  383. if (close_delegate != null)
  384. close_delegate = new Action<TimeSpan> (OnClose);
  385. return close_delegate.BeginInvoke (timeout, callback, state);
  386. }
  387. protected override sealed IAsyncResult OnBeginOpen (
  388. TimeSpan timeout, AsyncCallback callback, object state)
  389. {
  390. if (open_delegate == null)
  391. open_delegate = new Action<TimeSpan> (OnOpen);
  392. return open_delegate.BeginInvoke (timeout, callback, state);
  393. }
  394. protected override void OnClose (TimeSpan timeout)
  395. {
  396. DateTime start = DateTime.Now;
  397. ReleasePerformanceCounters ();
  398. List<ChannelDispatcherBase> l = new List<ChannelDispatcherBase> (ChannelDispatchers);
  399. foreach (ChannelDispatcherBase e in l) {
  400. try {
  401. TimeSpan ts = timeout - (DateTime.Now - start);
  402. if (ts < TimeSpan.Zero)
  403. e.Abort ();
  404. else
  405. e.Close (ts);
  406. } catch (Exception ex) {
  407. Console.WriteLine ("ServiceHostBase failed to close the channel dispatcher:");
  408. Console.WriteLine (ex);
  409. }
  410. }
  411. }
  412. protected override sealed void OnOpen (TimeSpan timeout)
  413. {
  414. DateTime start = DateTime.Now;
  415. InitializeRuntime ();
  416. foreach (var cd in ChannelDispatchers)
  417. cd.Open (timeout - (DateTime.Now - start));
  418. // FIXME: remove this hack. It should make sure that each ChannelDispatcher's loop has started, using WaitHandle.WaitAll() or something similar.
  419. System.Threading.Thread.Sleep (300);
  420. }
  421. protected override void OnEndClose (IAsyncResult result)
  422. {
  423. if (close_delegate == null)
  424. throw new InvalidOperationException ("Async close operation has not started");
  425. close_delegate.EndInvoke (result);
  426. }
  427. protected override sealed void OnEndOpen (IAsyncResult result)
  428. {
  429. if (open_delegate == null)
  430. throw new InvalidOperationException ("Aync open operation has not started");
  431. open_delegate.EndInvoke (result);
  432. }
  433. protected override void OnOpened ()
  434. {
  435. base.OnOpened ();
  436. }
  437. [MonoTODO]
  438. protected void ReleasePerformanceCounters ()
  439. {
  440. }
  441. void IDisposable.Dispose ()
  442. {
  443. Close ();
  444. }
  445. /*
  446. class SyncMethodInvoker : IOperationInvoker
  447. {
  448. readonly MethodInfo _methodInfo;
  449. public SyncMethodInvoker (MethodInfo methodInfo) {
  450. _methodInfo = methodInfo;
  451. }
  452. #region IOperationInvoker Members
  453. public bool IsSynchronous {
  454. get { return true; }
  455. }
  456. public object [] AllocateParameters () {
  457. return new object [_methodInfo.GetParameters ().Length];
  458. }
  459. public object Invoke (object instance, object [] parameters)
  460. {
  461. return _methodInfo.Invoke (instance, parameters);
  462. }
  463. public IAsyncResult InvokeBegin (object instance, object [] inputs, AsyncCallback callback, object state) {
  464. throw new NotSupportedException ();
  465. }
  466. public object InvokeEnd (object instance, out object [] outputs, IAsyncResult result) {
  467. throw new NotSupportedException ();
  468. }
  469. #endregion
  470. }
  471. class AsyncMethodInvoker : IOperationInvoker
  472. {
  473. readonly MethodInfo _beginMethodInfo, _endMethodInfo;
  474. public AsyncMethodInvoker (MethodInfo beginMethodInfo, MethodInfo endMethodInfo) {
  475. _beginMethodInfo = beginMethodInfo;
  476. _endMethodInfo = endMethodInfo;
  477. }
  478. #region IOperationInvoker Members
  479. public bool IsSynchronous {
  480. get { return false; }
  481. }
  482. public object [] AllocateParameters () {
  483. return new object [_beginMethodInfo.GetParameters ().Length - 2 + _endMethodInfo.GetParameters().Length-1];
  484. }
  485. public object Invoke (object instance, object [] parameters) {
  486. throw new NotImplementedException ("Can't invoke async method synchronously");
  487. //BUGBUG: need to differentiate between input and output parameters.
  488. IAsyncResult asyncResult = InvokeBegin(instance, parameters, delegate(IAsyncResult ignore) { }, null);
  489. asyncResult.AsyncWaitHandle.WaitOne();
  490. return InvokeEnd(instance, out parameters, asyncResult);
  491. }
  492. public IAsyncResult InvokeBegin (object instance, object [] inputs, AsyncCallback callback, object state) {
  493. if (inputs.Length + 2 != _beginMethodInfo.GetParameters ().Length)
  494. throw new ArgumentException ("Wrong number of input parameters");
  495. object [] fullargs = new object [_beginMethodInfo.GetParameters ().Length];
  496. Array.Copy (inputs, fullargs, inputs.Length);
  497. fullargs [inputs.Length] = callback;
  498. fullargs [inputs.Length + 1] = state;
  499. return (IAsyncResult) _beginMethodInfo.Invoke (instance, fullargs);
  500. }
  501. public object InvokeEnd (object instance, out object [] outputs, IAsyncResult asyncResult) {
  502. outputs = new object [_endMethodInfo.GetParameters ().Length - 1];
  503. object [] fullargs = new object [_endMethodInfo.GetParameters ().Length];
  504. fullargs [outputs.Length] = asyncResult;
  505. object result = _endMethodInfo.Invoke (instance, fullargs);
  506. Array.Copy (fullargs, outputs, outputs.Length);
  507. return result;
  508. }
  509. #endregion
  510. }
  511. */
  512. }
  513. partial class DispatcherBuilder
  514. {
  515. internal ChannelDispatcher BuildChannelDispatcher (Type serviceType, ServiceEndpoint se, BindingParameterCollection commonParams)
  516. {
  517. //Let all behaviors add their binding parameters
  518. AddBindingParameters (commonParams, se);
  519. //User the binding parameters to build the channel listener and Dispatcher
  520. IChannelListener lf = BuildListener (se, commonParams);
  521. ChannelDispatcher cd = new ChannelDispatcher (
  522. lf, se.Binding.Name);
  523. cd.InitializeServiceEndpoint (serviceType, se);
  524. return cd;
  525. }
  526. private void AddBindingParameters (BindingParameterCollection commonParams, ServiceEndpoint endPoint) {
  527. commonParams.Add (ChannelProtectionRequirements.CreateFromContract (endPoint.Contract));
  528. foreach (IContractBehavior b in endPoint.Contract.Behaviors)
  529. b.AddBindingParameters (endPoint.Contract, endPoint, commonParams);
  530. foreach (IEndpointBehavior b in endPoint.Behaviors)
  531. b.AddBindingParameters (endPoint, commonParams);
  532. foreach (OperationDescription operation in endPoint.Contract.Operations) {
  533. foreach (IOperationBehavior b in operation.Behaviors)
  534. b.AddBindingParameters (operation, commonParams);
  535. }
  536. }
  537. static IChannelListener BuildListener (ServiceEndpoint se,
  538. BindingParameterCollection pl)
  539. {
  540. Binding b = se.Binding;
  541. if (b.CanBuildChannelListener<IReplySessionChannel> (pl))
  542. return b.BuildChannelListener<IReplySessionChannel> (se.ListenUri, "", se.ListenUriMode, pl);
  543. if (b.CanBuildChannelListener<IReplyChannel> (pl))
  544. return b.BuildChannelListener<IReplyChannel> (se.ListenUri, "", se.ListenUriMode, pl);
  545. if (b.CanBuildChannelListener<IInputSessionChannel> (pl))
  546. return b.BuildChannelListener<IInputSessionChannel> (se.ListenUri, "", se.ListenUriMode, pl);
  547. if (b.CanBuildChannelListener<IInputChannel> (pl))
  548. return b.BuildChannelListener<IInputChannel> (se.ListenUri, "", se.ListenUriMode, pl);
  549. if (b.CanBuildChannelListener<IDuplexChannel> (pl))
  550. return b.BuildChannelListener<IDuplexChannel> (se.ListenUri, "", se.ListenUriMode, pl);
  551. if (b.CanBuildChannelListener<IDuplexSessionChannel> (pl))
  552. return b.BuildChannelListener<IDuplexSessionChannel> (se.ListenUri, "", se.ListenUriMode, pl);
  553. throw new InvalidOperationException ("None of the listener channel types is supported");
  554. }
  555. }
  556. }