PageRenderTime 57ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Microsoft.AspNet.SignalR.Core/Hubs/DefaultJavaScriptProxyGenerator.cs

https://github.com/mip1983/SignalR
C# | 195 lines | 163 code | 29 blank | 3 comment | 16 complexity | 52fe451b86cfd42d3df65d4e93a1827b MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Concurrent;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. namespace Microsoft.AspNet.SignalR.Hubs
  10. {
  11. public class DefaultJavaScriptProxyGenerator : IJavaScriptProxyGenerator
  12. {
  13. private static readonly Lazy<string> _template = new Lazy<string>(GetTemplate);
  14. private static readonly ConcurrentDictionary<string, string> _scriptCache = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
  15. private static readonly Type[] _numberTypes = new[] { typeof(byte), typeof(short), typeof(int), typeof(long), typeof(float), typeof(decimal), typeof(double) };
  16. private static readonly Type[] _dateTypes = new[] { typeof(DateTime), typeof(DateTimeOffset) };
  17. private const string ScriptResource = "Microsoft.AspNet.SignalR.Scripts.hubs.js";
  18. private readonly IHubManager _manager;
  19. private readonly IJavaScriptMinifier _javascriptMinifier;
  20. public DefaultJavaScriptProxyGenerator(IDependencyResolver resolver) :
  21. this(resolver.Resolve<IHubManager>(),
  22. resolver.Resolve<IJavaScriptMinifier>())
  23. {
  24. }
  25. public DefaultJavaScriptProxyGenerator(IHubManager manager, IJavaScriptMinifier javascriptMinifier)
  26. {
  27. _manager = manager;
  28. _javascriptMinifier = javascriptMinifier ?? NullJavaScriptMinifier.Instance;
  29. }
  30. public bool IsDebuggingEnabled { get; set; }
  31. public string GenerateProxy(string serviceUrl, bool includeDocComments = false)
  32. {
  33. string script;
  34. if (_scriptCache.TryGetValue(serviceUrl, out script))
  35. {
  36. return script;
  37. }
  38. var template = _template.Value;
  39. script = template.Replace("{serviceUrl}", serviceUrl);
  40. var hubs = new StringBuilder();
  41. var first = true;
  42. foreach (var descriptor in _manager.GetHubs().OrderBy(h => h.Name))
  43. {
  44. if (!first)
  45. {
  46. hubs.AppendLine(";");
  47. hubs.AppendLine();
  48. hubs.Append(" ");
  49. }
  50. GenerateType(hubs, descriptor, includeDocComments);
  51. first = false;
  52. }
  53. if (hubs.Length > 0)
  54. {
  55. hubs.Append(";");
  56. }
  57. script = script.Replace("/*hubs*/", hubs.ToString());
  58. if (!IsDebuggingEnabled)
  59. {
  60. script = _javascriptMinifier.Minify(script);
  61. }
  62. _scriptCache.TryAdd(serviceUrl, script);
  63. return script;
  64. }
  65. private void GenerateType(StringBuilder sb, HubDescriptor descriptor, bool includeDocComments)
  66. {
  67. // Get only actions with minimum number of parameters.
  68. var methods = GetMethods(descriptor);
  69. var members = methods.Select(m => m.Name).OrderBy(name => name).ToList();
  70. var hubName = GetDescriptorName(descriptor);
  71. sb.AppendFormat("signalR.{0} = signalR.hub.createHubProxy('{1}'); ", hubName, hubName).AppendLine();
  72. sb.AppendFormat(" signalR.{0}.client = {{ }};", hubName).AppendLine();
  73. sb.AppendFormat(" signalR.{0}.server = {{", hubName);
  74. bool first = true;
  75. foreach (var method in methods)
  76. {
  77. if (!first)
  78. {
  79. sb.Append(",").AppendLine();
  80. }
  81. this.GenerateMethod(sb, method, includeDocComments, hubName);
  82. first = false;
  83. }
  84. sb.AppendLine();
  85. sb.Append(" }");
  86. }
  87. protected virtual string GetDescriptorName(Descriptor descriptor)
  88. {
  89. string name = descriptor.Name;
  90. // If the name was not specified then do not camel case
  91. if (!descriptor.NameSpecified)
  92. {
  93. name = Json.CamelCase(name);
  94. }
  95. return name;
  96. }
  97. private IEnumerable<MethodDescriptor> GetMethods(HubDescriptor descriptor)
  98. {
  99. return from method in _manager.GetHubMethods(descriptor.Name)
  100. group method by method.Name into overloads
  101. let oload = (from overload in overloads
  102. orderby overload.Parameters.Count
  103. select overload).FirstOrDefault()
  104. select oload;
  105. }
  106. private void GenerateMethod(StringBuilder sb, MethodDescriptor method, bool includeDocComments, string hubName)
  107. {
  108. var parameterNames = method.Parameters.Select(p => p.Name).ToList();
  109. sb.AppendLine();
  110. sb.AppendFormat(" {0}: function ({1}) {{", GetDescriptorName(method), Commas(parameterNames)).AppendLine();
  111. if (includeDocComments)
  112. {
  113. sb.AppendFormat(" /// <summary>Calls the {0} method on the server-side {1} hub.&#10;Returns a jQuery.Deferred() promise.</summary>", method.Name, method.Hub.Name).AppendLine();
  114. var parameterDoc = method.Parameters.Select(p => String.Format(" /// <param name=\"{0}\" type=\"{1}\">Server side type is {2}</param>", p.Name, MapToJavaScriptType(p.Type), p.Type)).ToList();
  115. if (parameterDoc.Any())
  116. {
  117. sb.AppendLine(String.Join(Environment.NewLine, parameterDoc));
  118. }
  119. }
  120. sb.AppendFormat(" return signalR.{0}.invoke.apply(signalR.{0}, $.merge([\"{1}\"], $.makeArray(arguments)));", hubName, method.Name).AppendLine();
  121. sb.Append(" }");
  122. }
  123. private string MapToJavaScriptType(Type type)
  124. {
  125. if (!type.IsPrimitive && !(type == typeof(string)))
  126. {
  127. return "Object";
  128. }
  129. if (type == typeof(string))
  130. {
  131. return "String";
  132. }
  133. if (_numberTypes.Contains(type))
  134. {
  135. return "Number";
  136. }
  137. if (typeof(IEnumerable).IsAssignableFrom(type))
  138. {
  139. return "Array";
  140. }
  141. if (_dateTypes.Contains(type))
  142. {
  143. return "Date";
  144. }
  145. return String.Empty;
  146. }
  147. private static string Commas(IEnumerable<string> values)
  148. {
  149. return Commas(values, v => v);
  150. }
  151. private static string Commas<T>(IEnumerable<T> values, Func<T, string> selector)
  152. {
  153. return String.Join(", ", values.Select(selector));
  154. }
  155. private static string GetTemplate()
  156. {
  157. using (Stream resourceStream = typeof(DefaultJavaScriptProxyGenerator).Assembly.GetManifestResourceStream(ScriptResource))
  158. {
  159. using (var reader = new StreamReader(resourceStream))
  160. {
  161. return reader.ReadToEnd();
  162. }
  163. }
  164. }
  165. }
  166. }