DuplexChannelFactory.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel
  5. {
  6. using System.Collections.Generic;
  7. using System.ServiceModel.Description;
  8. using System.ServiceModel.Dispatcher;
  9. using System.ServiceModel.Channels;
  10. using System.Collections.ObjectModel;
  11. using System.Diagnostics;
  12. using System.IO;
  13. using System.Runtime.Serialization;
  14. using System.Text;
  15. using System.Threading;
  16. using System.ServiceModel.Diagnostics;
  17. using System.ServiceModel.Configuration;
  18. public class DuplexChannelFactory<TChannel> : ChannelFactory<TChannel>
  19. {
  20. //Type overloads
  21. public DuplexChannelFactory(Type callbackInstanceType)
  22. : this((object)callbackInstanceType)
  23. { }
  24. public DuplexChannelFactory(Type callbackInstanceType, Binding binding, String remoteAddress)
  25. : this((object)callbackInstanceType, binding, new EndpointAddress(remoteAddress))
  26. { }
  27. public DuplexChannelFactory(Type callbackInstanceType, Binding binding, EndpointAddress remoteAddress)
  28. : this((object)callbackInstanceType, binding, remoteAddress)
  29. { }
  30. public DuplexChannelFactory(Type callbackInstanceType, Binding binding)
  31. : this((object)callbackInstanceType, binding)
  32. { }
  33. public DuplexChannelFactory(Type callbackInstanceType, string endpointConfigurationName, EndpointAddress remoteAddress)
  34. : this((object)callbackInstanceType, endpointConfigurationName, remoteAddress)
  35. { }
  36. public DuplexChannelFactory(Type callbackInstanceType, string endpointConfigurationName)
  37. : this((object)callbackInstanceType, endpointConfigurationName)
  38. { }
  39. public DuplexChannelFactory(Type callbackInstanceType, ServiceEndpoint endpoint)
  40. : this((object)callbackInstanceType, endpoint)
  41. { }
  42. //InstanceContext overloads
  43. public DuplexChannelFactory(InstanceContext callbackInstance)
  44. : this((object)callbackInstance)
  45. { }
  46. public DuplexChannelFactory(InstanceContext callbackInstance, Binding binding, String remoteAddress)
  47. : this((object)callbackInstance, binding, new EndpointAddress(remoteAddress))
  48. { }
  49. public DuplexChannelFactory(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress)
  50. : this((object)callbackInstance, binding, remoteAddress)
  51. { }
  52. public DuplexChannelFactory(InstanceContext callbackInstance, Binding binding)
  53. : this((object)callbackInstance, binding)
  54. { }
  55. public DuplexChannelFactory(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress)
  56. : this((object)callbackInstance, endpointConfigurationName, remoteAddress)
  57. { }
  58. public DuplexChannelFactory(InstanceContext callbackInstance, string endpointConfigurationName)
  59. : this((object)callbackInstance, endpointConfigurationName)
  60. { }
  61. public DuplexChannelFactory(InstanceContext callbackInstance, ServiceEndpoint endpoint)
  62. : this((object)callbackInstance, endpoint)
  63. { }
  64. // TChannel provides ContractDescription
  65. public DuplexChannelFactory(object callbackObject)
  66. : base(typeof(TChannel))
  67. {
  68. using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
  69. {
  70. if (DiagnosticUtility.ShouldUseActivity)
  71. {
  72. ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructChannelFactory, TraceUtility.CreateSourceString(this)), ActivityType.Construct);
  73. }
  74. if (callbackObject == null)
  75. {
  76. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackObject");
  77. }
  78. this.CheckAndAssignCallbackInstance(callbackObject);
  79. this.InitializeEndpoint((string)null, (EndpointAddress)null);
  80. }
  81. }
  82. // TChannel provides ContractDescription, attr/config [TChannel,name] provides Address,Binding
  83. public DuplexChannelFactory(object callbackObject, string endpointConfigurationName)
  84. : this(callbackObject, endpointConfigurationName, null)
  85. {
  86. }
  87. // TChannel provides ContractDescription, attr/config [TChannel,name] provides Binding, provide Address explicitly
  88. public DuplexChannelFactory(object callbackObject, string endpointConfigurationName, EndpointAddress remoteAddress)
  89. : base(typeof(TChannel))
  90. {
  91. using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
  92. {
  93. if (DiagnosticUtility.ShouldUseActivity)
  94. {
  95. ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructChannelFactory, TraceUtility.CreateSourceString(this)), ActivityType.Construct);
  96. }
  97. if (callbackObject == null)
  98. {
  99. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackObject");
  100. }
  101. if (endpointConfigurationName == null)
  102. {
  103. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
  104. }
  105. this.CheckAndAssignCallbackInstance(callbackObject);
  106. this.InitializeEndpoint(endpointConfigurationName, remoteAddress);
  107. }
  108. }
  109. // TChannel provides ContractDescription, attr/config [TChannel,name] provides Address,Binding
  110. public DuplexChannelFactory(object callbackObject, Binding binding)
  111. : this(callbackObject, binding, (EndpointAddress)null)
  112. {
  113. }
  114. // TChannel provides ContractDescription, provide Address,Binding explicitly
  115. public DuplexChannelFactory(object callbackObject, Binding binding, String remoteAddress)
  116. : this(callbackObject, binding, new EndpointAddress(remoteAddress))
  117. {
  118. }
  119. // TChannel provides ContractDescription, provide Address,Binding explicitly
  120. public DuplexChannelFactory(object callbackObject, Binding binding, EndpointAddress remoteAddress)
  121. : base(typeof(TChannel))
  122. {
  123. using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
  124. {
  125. if (DiagnosticUtility.ShouldUseActivity)
  126. {
  127. ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructChannelFactory, TraceUtility.CreateSourceString(this)), ActivityType.Construct);
  128. }
  129. if (callbackObject == null)
  130. {
  131. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackObject");
  132. }
  133. if (binding == null)
  134. {
  135. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
  136. }
  137. this.CheckAndAssignCallbackInstance(callbackObject);
  138. this.InitializeEndpoint(binding, remoteAddress);
  139. }
  140. }
  141. // provide ContractDescription,Address,Binding explicitly
  142. public DuplexChannelFactory(object callbackObject, ServiceEndpoint endpoint)
  143. : base(typeof(TChannel))
  144. {
  145. using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
  146. {
  147. if (DiagnosticUtility.ShouldUseActivity)
  148. {
  149. ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructChannelFactory, TraceUtility.CreateSourceString(this)), ActivityType.Construct);
  150. }
  151. if (callbackObject == null)
  152. {
  153. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackObject");
  154. }
  155. if (endpoint == null)
  156. {
  157. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
  158. }
  159. this.CheckAndAssignCallbackInstance(callbackObject);
  160. this.InitializeEndpoint(endpoint);
  161. }
  162. }
  163. internal void CheckAndAssignCallbackInstance(object callbackInstance)
  164. {
  165. if (callbackInstance is Type)
  166. {
  167. this.CallbackType = (Type)callbackInstance;
  168. }
  169. else if (callbackInstance is InstanceContext)
  170. {
  171. this.CallbackInstance = (InstanceContext)callbackInstance;
  172. }
  173. else
  174. {
  175. this.CallbackInstance = new InstanceContext(callbackInstance);
  176. }
  177. }
  178. public TChannel CreateChannel(InstanceContext callbackInstance)
  179. {
  180. return CreateChannel(callbackInstance, CreateEndpointAddress(this.Endpoint), null);
  181. }
  182. public TChannel CreateChannel(InstanceContext callbackInstance, EndpointAddress address)
  183. {
  184. if (address == null)
  185. {
  186. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  187. }
  188. return CreateChannel(callbackInstance, address, address.Uri);
  189. }
  190. public override TChannel CreateChannel(EndpointAddress address, Uri via)
  191. {
  192. return CreateChannel(this.CallbackInstance, address, via);
  193. }
  194. public virtual TChannel CreateChannel(InstanceContext callbackInstance, EndpointAddress address, Uri via)
  195. {
  196. if (address == null)
  197. {
  198. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
  199. }
  200. if (this.CallbackType != null && callbackInstance == null)
  201. {
  202. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCreateDuplexChannelNoCallback1)));
  203. }
  204. if (callbackInstance == null)
  205. {
  206. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCreateDuplexChannelNoCallback)));
  207. }
  208. if (callbackInstance.UserObject == null)
  209. {
  210. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCreateDuplexChannelNoCallbackUserObject)));
  211. }
  212. if (!this.HasDuplexOperations())
  213. {
  214. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCreateDuplexChannel1, this.Endpoint.Contract.Name)));
  215. }
  216. Type userObjectType = callbackInstance.UserObject.GetType();
  217. Type callbackType = this.Endpoint.Contract.CallbackContractType;
  218. if (callbackType != null && !callbackType.IsAssignableFrom(userObjectType))
  219. {
  220. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
  221. SR.SFxCreateDuplexChannelBadCallbackUserObject, callbackType)));
  222. }
  223. EnsureOpened();
  224. TChannel result = (TChannel)this.ServiceChannelFactory.CreateChannel(typeof(TChannel), address, via);
  225. IDuplexContextChannel duplexChannel = result as IDuplexContextChannel;
  226. if (duplexChannel != null)
  227. {
  228. duplexChannel.CallbackInstance = callbackInstance;
  229. }
  230. return result;
  231. }
  232. //Static funtions to create channels
  233. static InstanceContext GetInstanceContextForObject(object callbackObject)
  234. {
  235. if (callbackObject is InstanceContext)
  236. {
  237. return (InstanceContext)callbackObject;
  238. }
  239. return new InstanceContext(callbackObject);
  240. }
  241. public static TChannel CreateChannel(object callbackObject, String endpointConfigurationName)
  242. {
  243. return CreateChannel(GetInstanceContextForObject(callbackObject), endpointConfigurationName);
  244. }
  245. public static TChannel CreateChannel(object callbackObject, Binding binding, EndpointAddress endpointAddress)
  246. {
  247. return CreateChannel(GetInstanceContextForObject(callbackObject), binding, endpointAddress);
  248. }
  249. public static TChannel CreateChannel(object callbackObject, Binding binding, EndpointAddress endpointAddress, Uri via)
  250. {
  251. return CreateChannel(GetInstanceContextForObject(callbackObject), binding, endpointAddress, via);
  252. }
  253. public static TChannel CreateChannel(InstanceContext callbackInstance, String endpointConfigurationName)
  254. {
  255. DuplexChannelFactory<TChannel> channelFactory = new DuplexChannelFactory<TChannel>(callbackInstance, endpointConfigurationName);
  256. TChannel channel = channelFactory.CreateChannel();
  257. SetFactoryToAutoClose(channel);
  258. return channel;
  259. }
  260. public static TChannel CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress)
  261. {
  262. DuplexChannelFactory<TChannel> channelFactory = new DuplexChannelFactory<TChannel>(callbackInstance, binding, endpointAddress);
  263. TChannel channel = channelFactory.CreateChannel();
  264. SetFactoryToAutoClose(channel);
  265. return channel;
  266. }
  267. public static TChannel CreateChannel(InstanceContext callbackInstance, Binding binding, EndpointAddress endpointAddress, Uri via)
  268. {
  269. DuplexChannelFactory<TChannel> channelFactory = new DuplexChannelFactory<TChannel>(callbackInstance, binding);
  270. TChannel channel = channelFactory.CreateChannel(endpointAddress, via);
  271. SetFactoryToAutoClose(channel);
  272. return channel;
  273. }
  274. }
  275. }