Guest User

Untitled

a guest
Feb 19th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.08 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ServiceModel;
  6. using System.Reflection;
  7.  
  8. using System.Runtime.Serialization;
  9.  
  10. namespace IServiceOriented.ServiceBus
  11. {
  12. /// <summary>
  13. /// Provides support for dispatching messages to WCF endpoints.
  14. /// </summary>
  15. [Serializable]
  16. [DataContract]
  17. public class WcfDispatcher : Dispatcher
  18. {
  19. public WcfDispatcher()
  20. {
  21.  
  22. }
  23.  
  24. public WcfDispatcher(WcfDispatchStyle dispatchStyle)
  25. {
  26. DispatchStyle = dispatchStyle;
  27. }
  28.  
  29. // TODO: if the same dispatcher instance is reused with another type this will be invalid
  30. void initActionLookup()
  31. {
  32. Dictionary<string, MethodInfo> actionLookup = new Dictionary<string, MethodInfo>();
  33. foreach (MethodInfo method in Endpoint.ContractType.GetMethods())
  34. {
  35. object[] attributes = method.GetCustomAttributes(typeof(OperationContractAttribute), false);
  36. if (attributes.Length > 0)
  37. {
  38. OperationContractAttribute oca = (OperationContractAttribute)attributes[0];
  39. string action = oca.Action;
  40. if (action == null)
  41. {
  42. action = method.Name;
  43. }
  44. actionLookup.Add(action, method);
  45. }
  46. }
  47. _actionLookup = actionLookup;
  48.  
  49. }
  50.  
  51. // TODO: if the same dispatcher instance is reused with another type this will be invalid
  52. void initTypeLookup()
  53. {
  54. Dictionary<Type, MethodInfo> typeLookup = new Dictionary<Type, MethodInfo>();
  55. foreach (MethodInfo method in Endpoint.ContractType.GetMethods())
  56. {
  57. object[] attributes = method.GetCustomAttributes(typeof(OperationContractAttribute), false);
  58. if (attributes.Length > 0)
  59. {
  60. OperationContractAttribute oca = (OperationContractAttribute)attributes[0];
  61. ParameterInfo[] parameters = method.GetParameters();
  62. if (parameters.Length == 1)
  63. {
  64. typeLookup.Add(parameters[0].ParameterType, method);
  65. }
  66. }
  67. }
  68. _typeLookup = typeLookup;
  69. }
  70.  
  71. /// <summary>
  72. /// Specifies whether to apply the credentials of the user that published the message.
  73. /// </summary>
  74. /// <remarks>Credentials will be passed as UserName credentials, not using Windows impersonation or delegation.</remarks>
  75. [DataMember]
  76. public bool ApplyCredentials
  77. {
  78. get;
  79. set;
  80. }
  81.  
  82. protected virtual void ApplySecurityContext(ChannelFactory factory)
  83. {
  84. if (ApplyCredentials)
  85. {
  86. if (DispatchContext.MessageDelivery.Context.ContainsKey(MessageDelivery.PrimaryIdentityNameKey))
  87. {
  88. factory.Credentials.UserName.UserName = (string)DispatchContext.MessageDelivery.Context[MessageDelivery.PrimaryIdentityNameKey];
  89. factory.Credentials.UserName.Password = "";
  90. }
  91. }
  92. }
  93.  
  94. protected override void Dispatch(SubscriptionEndpoint endpoint, MessageDelivery messageDelivery)
  95. {
  96. // TODO: Clean this up. Creating channel factory for each call is expensive
  97. Type channelType = typeof(ChannelFactory<>).MakeGenericType(endpoint.ContractType);
  98. object factory = Activator.CreateInstance(channelType, endpoint.ConfigurationName);
  99. ((ChannelFactory)factory).Endpoint.Address = new EndpointAddress(endpoint.Address);
  100.  
  101. ApplySecurityContext((ChannelFactory)factory);
  102.  
  103. IClientChannel proxy = (IClientChannel)channelType.GetMethod("CreateChannel", new Type[] { }).Invoke(factory, new object[] { });
  104. bool success = false;
  105. try
  106. {
  107. MethodInfo methodInfo;
  108.  
  109. if (DispatchStyle == WcfDispatchStyle.Action)
  110. {
  111. if (_actionLookup == null)
  112. {
  113. initActionLookup();
  114. }
  115.  
  116. if (!_actionLookup.TryGetValue(messageDelivery.Action, out methodInfo))
  117. {
  118. foreach (string a in _actionLookup.Keys)
  119. {
  120. if (a == "*")
  121. {
  122. methodInfo = _actionLookup[a];
  123. break;
  124. }
  125. }
  126. }
  127. }
  128. else if (DispatchStyle == WcfDispatchStyle.Type)
  129. {
  130. if (_typeLookup == null)
  131. {
  132. initTypeLookup();
  133. }
  134.  
  135. if (_typeLookup.TryGetValue(messageDelivery.Message.GetType(), out methodInfo))
  136. {
  137. foreach (Type t in _typeLookup.Keys)
  138. {
  139. if (t == typeof(object))
  140. {
  141. methodInfo = _typeLookup[t];
  142. break;
  143. }
  144. }
  145. }
  146. }
  147. else
  148. {
  149. throw new NotSupportedException();
  150. }
  151.  
  152. if (methodInfo != null)
  153. {
  154. methodInfo.Invoke(proxy, new object[] { messageDelivery.Message });
  155. }
  156. else
  157. {
  158. throw new InvalidOperationException("Matching method not found");
  159. }
  160. proxy.Close();
  161. success = true;
  162. }
  163. finally
  164. {
  165. if (!success)
  166. {
  167. proxy.Abort();
  168. }
  169. }
  170. }
  171.  
  172. [NonSerialized]
  173. Dictionary<string, MethodInfo> _actionLookup;
  174.  
  175. [NonSerialized]
  176. Dictionary<Type, MethodInfo> _typeLookup;
  177.  
  178.  
  179. /// <summary>
  180. /// Gets or sets the way that this dispatcher will determine which operation to invoke.
  181. /// </summary>
  182. public WcfDispatchStyle DispatchStyle
  183. {
  184. get;
  185. set;
  186. }
  187. }
  188.  
  189. public enum WcfDispatchStyle
  190. {
  191. /// <summary>
  192. /// Dispatch by finding an operation that matches the requested action (or "*" if no direct match)
  193. /// </summary>
  194. Action,
  195. /// <summary>
  196. /// Dispatch by finding an operation that accepts the requested message type (or object if no direct match)
  197. /// </summary>
  198. Type
  199. }
  200.  
  201. }
Add Comment
Please, Sign In to add comment