WCFProxy.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. 
  2. using System;
  3. using System.ServiceModel;
  4. //using Curtain.WCF.Contract;
  5. namespace Curtain.WCF.Proxy
  6. {
  7. /// <summary>
  8. /// WCF服务代理基类
  9. /// </summary>
  10. public abstract class WCFProxy<TChannel> : IDisposable//, IWCFProxy
  11. where TChannel : class//, IWCFContract
  12. {
  13. #region 常量
  14. #endregion
  15. #region 成员变量
  16. /// <summary>
  17. /// 终结点的配置名称
  18. /// </summary>
  19. private readonly string _endpointName = null;
  20. private readonly string _serviceName = null;
  21. /// <summary>
  22. /// WCF代理配置
  23. /// </summary>
  24. private WCFProxySetting _setting = null;
  25. /// <summary>
  26. /// WCF代理配置版本
  27. /// </summary>
  28. private int _settingVersion = 0;
  29. #endregion
  30. #region 构造
  31. /// <summary>
  32. /// WCF服务代理基类
  33. /// </summary>
  34. /// <param name="endpointName"></param>
  35. /// <param name="settingName"></param>
  36. /// <param name="serviceName"></param>
  37. protected WCFProxy(string endpointName, string settingName, string serviceName)
  38. {
  39. if (string.IsNullOrWhiteSpace(endpointName))
  40. {
  41. throw new ArgumentNullException("endpointName");
  42. }
  43. this._endpointName = endpointName;
  44. this._serviceName = serviceName;
  45. this._setting = WCFProxySetting.CreateSetting(settingName);
  46. }
  47. /// <summary>
  48. /// WCF服务代理基类
  49. /// </summary>
  50. /// <param name="endpointName"></param>
  51. /// <param name="setting"></param>
  52. protected WCFProxy(string endpointName, WCFProxySetting setting, string serviceName)
  53. {
  54. if (string.IsNullOrWhiteSpace(endpointName))
  55. {
  56. throw new ArgumentNullException("endpointName");
  57. }
  58. this._endpointName = endpointName;
  59. this._serviceName = serviceName;
  60. this._setting = (setting ?? WCFProxySetting.DefaultSetting);
  61. }
  62. #endregion
  63. #region 属性
  64. public string EndpointName
  65. {
  66. get
  67. {
  68. return this._endpointName;
  69. }
  70. }
  71. public string ServiceName
  72. {
  73. get
  74. {
  75. return this._serviceName;
  76. }
  77. }
  78. /// <summary>
  79. /// WCF代理配置
  80. /// </summary>
  81. public WCFProxySetting ProxySetting
  82. {
  83. get
  84. {
  85. return this._setting;
  86. }
  87. }
  88. /// <summary>
  89. /// 信道工厂
  90. /// </summary>
  91. public ChannelFactory<TChannel> ChannelFactory { get; private set; } = null;
  92. #endregion
  93. #region 公有方法
  94. /// <summary>
  95. /// 执行
  96. /// </summary>
  97. /// <param name="serviceInvocation"></param>
  98. /// <param name="timeout">超时(分钟)</param>
  99. public virtual void Invoke(Action<TChannel> serviceInvocation, double timeout = 0)
  100. {
  101. IContextChannel contextChannel = null;
  102. string methodName = serviceInvocation.Method.ToString();
  103. try
  104. {
  105. TChannel channel;
  106. if (this._setting.Type == 1)
  107. {
  108. channel = this.GetServerInstance();
  109. }
  110. else
  111. {
  112. this.OpenChannelFactory();
  113. channel = this.ChannelFactory.CreateChannel();
  114. contextChannel = channel as IContextChannel;
  115. if (contextChannel != null)
  116. {
  117. if (timeout > WCFProxySetting.OPERATION_TIMEOUT_MAX)
  118. {
  119. timeout = WCFProxySetting.OPERATION_TIMEOUT_MAX;
  120. }
  121. if (timeout > 0)
  122. {
  123. contextChannel.OperationTimeout = TimeSpan.FromMinutes(timeout);
  124. }
  125. }
  126. }
  127. serviceInvocation(channel);
  128. this.InvokeDone<object>(methodName, null, true);
  129. }
  130. catch (Exception ex)
  131. {
  132. Exception newEx = this.InvokeException(methodName, ex);
  133. if (newEx == null)
  134. {
  135. return;
  136. }
  137. throw newEx;
  138. }
  139. finally
  140. {
  141. if (contextChannel != null)
  142. {
  143. try
  144. {
  145. contextChannel.Close();
  146. }
  147. catch
  148. {
  149. contextChannel.Abort();
  150. }
  151. }
  152. }
  153. }
  154. /// <summary>
  155. /// 执行
  156. /// </summary>
  157. /// <typeparam name="TResult"></typeparam>
  158. /// <param name="serviceInvocation"></param>
  159. /// <param name="timeout">超时(分钟)</param>
  160. /// <returns></returns>
  161. public virtual TResult Invoke<TResult>(Func<TChannel, TResult> serviceInvocation,
  162. double timeout = 0)
  163. {
  164. IContextChannel contextChannel = null;
  165. string methodName = serviceInvocation.Method.ToString();
  166. try
  167. {
  168. TChannel channel;
  169. //if (this._setting.Type == 1)
  170. //{
  171. // channel = this.GetServerInstance();
  172. //}
  173. ////else
  174. //if(channel == null)
  175. {
  176. this.OpenChannelFactory();
  177. channel = this.ChannelFactory.CreateChannel();
  178. contextChannel = channel as IContextChannel;
  179. if (contextChannel != null)
  180. {
  181. if (timeout > WCFProxySetting.OPERATION_TIMEOUT_MAX)
  182. {
  183. timeout = WCFProxySetting.OPERATION_TIMEOUT_MAX;
  184. }
  185. if (timeout > 0)
  186. {
  187. contextChannel.OperationTimeout = TimeSpan.FromMinutes(timeout);
  188. }
  189. }
  190. }
  191. TResult result = serviceInvocation(channel);
  192. result = this.InvokeDone<TResult>(methodName, result);
  193. return result;
  194. }
  195. catch (Exception ex)
  196. {
  197. Exception newEx = this.InvokeException(methodName, ex);
  198. if (newEx == null)
  199. {
  200. return default;
  201. }
  202. throw newEx;
  203. }
  204. finally
  205. {
  206. if (contextChannel != null)
  207. {
  208. try
  209. {
  210. contextChannel.Close();
  211. }
  212. catch
  213. {
  214. contextChannel.Abort();
  215. }
  216. }
  217. }
  218. }
  219. /// <summary>
  220. /// 关闭通道工厂
  221. /// </summary>
  222. public void CloseChannelFactory()
  223. {
  224. try
  225. {
  226. this.ChannelFactory.Close();
  227. }
  228. catch
  229. {
  230. this.ChannelFactory.Abort();
  231. }
  232. finally
  233. {
  234. this.ChannelFactory = null;
  235. }
  236. }
  237. /// <summary>
  238. /// 释放分配的资源
  239. /// </summary>
  240. public void Dispose()
  241. {
  242. this._setting = null;
  243. this.CloseChannelFactory();
  244. }
  245. #endregion
  246. #region 保护方法
  247. protected virtual TChannel GetServerInstance()
  248. {
  249. //throw new NotImplementedException();
  250. return null;
  251. }
  252. /// <summary>
  253. /// 异常处理
  254. /// 1.写日志
  255. /// 2.客户端连接异常处理
  256. /// 3.服务端异常处理
  257. /// </summary>
  258. /// <param name="cre"></param>
  259. /// <param name="sre"></param>
  260. /// <param name="ex"></param>
  261. /// <returns>抛出未处理异常</returns>
  262. protected virtual Exception InvokeException(string methodName, Exception ex)
  263. {
  264. return ex;
  265. }
  266. /// <summary>
  267. /// 请求被处理后
  268. /// 1.如果服务端异常已处理,写日志,提示消息等处理。
  269. /// </summary>
  270. /// <param name="result"></param>
  271. protected virtual TResult InvokeDone<TResult>(string methodName, TResult result, bool isOneWay = false)
  272. {
  273. return result;
  274. }
  275. #endregion
  276. #region 私有方法
  277. /// <summary>
  278. /// 打开通道工厂
  279. /// </summary>
  280. protected void OpenChannelFactory()
  281. {
  282. lock (this)
  283. {
  284. if (this.ChannelFactory != null &&
  285. this._settingVersion != this._setting.Version)
  286. {
  287. this.CloseChannelFactory();
  288. }
  289. if (this.ChannelFactory == null)
  290. {
  291. this._settingVersion = this._setting.Version;
  292. EndpointAddress remoteAddress = new EndpointAddress(this._setting.GetEndpointAddress(this._serviceName));
  293. this.ChannelFactory = new ChannelFactory<TChannel>(this._endpointName, remoteAddress);
  294. this.ChannelFactory.Open();
  295. }
  296. }
  297. }
  298. #endregion
  299. }
  300. }