DemoHubSample.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. #if !BESTHTTP_DISABLE_SIGNALR
  2. using System;
  3. using UnityEngine;
  4. using BestHTTP.SignalR;
  5. using BestHTTP.SignalR.Hubs;
  6. using BestHTTP.SignalR.Messages;
  7. using BestHTTP.SignalR.JsonEncoders;
  8. namespace BestHTTP.Examples
  9. {
  10. public sealed class DemoHubSample : MonoBehaviour
  11. {
  12. readonly Uri URI = new Uri(GUIHelper.BaseURL + "/signalr");
  13. /// <summary>
  14. /// The SignalR connection instance
  15. /// </summary>
  16. Connection signalRConnection;
  17. /// <summary>
  18. /// DemoHub client side implementation
  19. /// </summary>
  20. DemoHub demoHub;
  21. /// <summary>
  22. /// TypedDemoHub client side implementation
  23. /// </summary>
  24. TypedDemoHub typedDemoHub;
  25. /// <summary>
  26. /// VB .NET Hub
  27. /// </summary>
  28. Hub vbDemoHub;
  29. /// <summary>
  30. /// Result of the VB demo's ReadStateValue call
  31. /// </summary>
  32. string vbReadStateResult = string.Empty;
  33. Vector2 scrollPos;
  34. void Start()
  35. {
  36. // Create the hubs
  37. demoHub = new DemoHub();
  38. typedDemoHub = new TypedDemoHub();
  39. vbDemoHub = new Hub("vbdemo");
  40. // Create the SignalR connection, passing all the three hubs to it
  41. signalRConnection = new Connection(URI, demoHub, typedDemoHub, vbDemoHub);
  42. // Switch from the default encoder to the LitJson Encoder because it can handle the complex types too.
  43. signalRConnection.JsonEncoder = new LitJsonEncoder();
  44. // Call the demo functions when we successfully connect to the server
  45. signalRConnection.OnConnected += (connection) =>
  46. {
  47. var person = new { Name = "Foo", Age = 20, Address = new { Street = "One Microsoft Way", Zip = "98052" } };
  48. // Call the demo functions
  49. demoHub.AddToGroups();
  50. demoHub.GetValue();
  51. demoHub.TaskWithException();
  52. demoHub.GenericTaskWithException();
  53. demoHub.SynchronousException();
  54. demoHub.DynamicTask();
  55. demoHub.PassingDynamicComplex(person);
  56. demoHub.SimpleArray(new int[] { 5, 5, 6 });
  57. demoHub.ComplexType(person);
  58. demoHub.ComplexArray(new object[] { person, person, person });
  59. demoHub.ReportProgress("Long running job!");
  60. demoHub.Overload();
  61. // set some state
  62. demoHub.State["name"] = "Testing state!";
  63. demoHub.ReadStateValue();
  64. demoHub.PlainTask();
  65. demoHub.GenericTaskWithContinueWith();
  66. typedDemoHub.Echo("Typed echo callback");
  67. // vbDemo is not wrapped in a hub class, it would contain only one function
  68. vbDemoHub.Call("readStateValue", (hub, msg, result) => vbReadStateResult = string.Format("Read some state from VB.NET! => {0}", result.ReturnValue == null ? "undefined" : result.ReturnValue.ToString()));
  69. };
  70. // Start opening the signalR connection
  71. signalRConnection.Open();
  72. }
  73. void OnDestroy()
  74. {
  75. // Close the connection when we are closing this sample
  76. signalRConnection.Close();
  77. }
  78. void OnGUI()
  79. {
  80. GUIHelper.DrawArea(GUIHelper.ClientArea, true, () =>
  81. {
  82. scrollPos = GUILayout.BeginScrollView(scrollPos, false, false);
  83. GUILayout.BeginVertical();
  84. demoHub.Draw();
  85. typedDemoHub.Draw();
  86. GUILayout.Label("Read State Value");
  87. GUILayout.BeginHorizontal();
  88. GUILayout.Space(20);
  89. GUILayout.Label(vbReadStateResult);
  90. GUILayout.EndHorizontal();
  91. GUILayout.Space(10);
  92. GUILayout.EndVertical();
  93. GUILayout.EndScrollView();
  94. });
  95. }
  96. }
  97. /// <summary>
  98. /// Wrapper class of the 'TypedDemoHub' hub
  99. /// </summary>
  100. class TypedDemoHub : Hub
  101. {
  102. string typedEchoResult = string.Empty;
  103. string typedEchoClientResult = string.Empty;
  104. public TypedDemoHub()
  105. : base("typeddemohub")
  106. {
  107. // Setup server-called functions
  108. base.On("Echo", Echo);
  109. }
  110. #region Server Called Functions
  111. /// <summary>
  112. /// Server-called, client side implementation of the Echo function
  113. /// </summary>
  114. private void Echo(Hub hub, MethodCallMessage methodCall)
  115. {
  116. typedEchoClientResult = string.Format("{0} #{1} triggered!", methodCall.Arguments[0], methodCall.Arguments[1]);
  117. }
  118. #endregion
  119. #region Client Called Function(s)
  120. /// <summary>
  121. /// Client-called, server side implementation of the Echo function.
  122. /// When the function successfully executed on the server the OnEcho_Done callback function will be called.
  123. /// </summary>
  124. public void Echo(string msg)
  125. {
  126. base.Call("echo", OnEcho_Done, msg);
  127. }
  128. /// <summary>
  129. /// When the function successfully executed on the server this callback function will be called.
  130. /// </summary>
  131. private void OnEcho_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  132. {
  133. typedEchoResult = "TypedDemoHub.Echo(string message) invoked!";
  134. }
  135. #endregion
  136. public void Draw()
  137. {
  138. GUILayout.Label("Typed callback");
  139. GUILayout.BeginHorizontal();
  140. GUILayout.Space(20);
  141. GUILayout.BeginVertical();
  142. GUILayout.Label(typedEchoResult);
  143. GUILayout.Label(typedEchoClientResult);
  144. GUILayout.EndVertical();
  145. GUILayout.EndHorizontal();
  146. GUILayout.Space(10);
  147. }
  148. }
  149. /// <summary>
  150. /// A wrapper class for the 'DemoHub' hub.
  151. /// </summary>
  152. class DemoHub : Hub
  153. {
  154. #region Private fields
  155. // These fields are here to store results of the function calls
  156. float longRunningJobProgress = 0f;
  157. string longRunningJobStatus = "Not Started!";
  158. string fromArbitraryCodeResult = string.Empty;
  159. string groupAddedResult = string.Empty;
  160. string dynamicTaskResult = string.Empty;
  161. string genericTaskResult = string.Empty;
  162. string taskWithExceptionResult = string.Empty;
  163. string genericTaskWithExceptionResult = string.Empty;
  164. string synchronousExceptionResult = string.Empty;
  165. string invokingHubMethodWithDynamicResult = string.Empty;
  166. string simpleArrayResult = string.Empty;
  167. string complexTypeResult = string.Empty;
  168. string complexArrayResult = string.Empty;
  169. string voidOverloadResult = string.Empty;
  170. string intOverloadResult = string.Empty;
  171. string readStateResult = string.Empty;
  172. string plainTaskResult = string.Empty;
  173. string genericTaskWithContinueWithResult = string.Empty;
  174. GUIMessageList invokeResults = new GUIMessageList();
  175. #endregion
  176. public DemoHub()
  177. : base("demo")
  178. {
  179. // Setup server-called functions
  180. base.On("invoke", Invoke);
  181. base.On("signal", Signal);
  182. base.On("groupAdded", GroupAdded);
  183. base.On("fromArbitraryCode", FromArbitraryCode);
  184. }
  185. #region Client Called Functions
  186. #region ReportProgress
  187. public void ReportProgress(string arg)
  188. {
  189. Call("reportProgress", OnLongRunningJob_Done, null, OnLongRunningJob_Progress, arg);
  190. }
  191. public void OnLongRunningJob_Progress(Hub hub, ClientMessage originialMessage, ProgressMessage progress)
  192. {
  193. longRunningJobProgress = (float)progress.Progress;
  194. longRunningJobStatus = progress.Progress.ToString() + "%";
  195. }
  196. public void OnLongRunningJob_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  197. {
  198. longRunningJobStatus = result.ReturnValue.ToString();
  199. MultipleCalls();
  200. }
  201. #endregion
  202. public void MultipleCalls()
  203. {
  204. base.Call("multipleCalls");
  205. }
  206. #region DynamicTask
  207. public void DynamicTask()
  208. {
  209. base.Call("dynamicTask", OnDynamicTask_Done, OnDynamicTask_Failed);
  210. }
  211. private void OnDynamicTask_Failed(Hub hub, ClientMessage originalMessage, FailureMessage result)
  212. {
  213. dynamicTaskResult = string.Format("The dynamic task failed :( {0}", result.ErrorMessage);
  214. }
  215. private void OnDynamicTask_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  216. {
  217. dynamicTaskResult = string.Format("The dynamic task! {0}", result.ReturnValue);
  218. }
  219. #endregion
  220. public void AddToGroups()
  221. {
  222. base.Call("addToGroups");
  223. }
  224. public void GetValue()
  225. {
  226. base.Call("getValue", (hub, msg, result) => genericTaskResult = string.Format("The value is {0} after 5 seconds", result.ReturnValue));
  227. }
  228. public void TaskWithException()
  229. {
  230. // This method call must fail, so only error handler added
  231. base.Call("taskWithException", null, (Hub hub, ClientMessage msg, FailureMessage error) => taskWithExceptionResult = string.Format("Error: {0}", error.ErrorMessage));
  232. }
  233. public void GenericTaskWithException()
  234. {
  235. // This method call must fail, so only error handler added
  236. base.Call("genericTaskWithException", null, (Hub hub, ClientMessage msg, FailureMessage error) => genericTaskWithExceptionResult = string.Format("Error: {0}", error.ErrorMessage));
  237. }
  238. public void SynchronousException()
  239. {
  240. // This method call must fail, so only error handler added
  241. base.Call("synchronousException", null, (Hub hub, ClientMessage msg, FailureMessage error) => synchronousExceptionResult = string.Format("Error: {0}", error.ErrorMessage));
  242. }
  243. public void PassingDynamicComplex(object person)
  244. {
  245. base.Call("passingDynamicComplex", (hub, msg, result) => invokingHubMethodWithDynamicResult = string.Format("The person's age is {0}", result.ReturnValue), person);
  246. }
  247. public void SimpleArray(int[] array)
  248. {
  249. base.Call("simpleArray", (hub, msg, result) => simpleArrayResult = "Simple array works!", array);
  250. }
  251. public void ComplexType(object person)
  252. {
  253. base.Call("complexType", (hub, msg, result) => complexTypeResult = string.Format("Complex Type -> {0}", (this as IHub).Connection.JsonEncoder.Encode(this.State["person"])), person);
  254. }
  255. public void ComplexArray(object[] complexArray)
  256. {
  257. // We need to cast the object array to object to keep it as an array
  258. // http://stackoverflow.com/questions/36350/how-to-pass-a-single-object-to-a-params-object
  259. base.Call("ComplexArray", (hub, msg, result) => complexArrayResult = "Complex Array Works!", (object)complexArray);
  260. }
  261. #region Overloads
  262. public void Overload()
  263. {
  264. base.Call("Overload", OnVoidOverload_Done);
  265. }
  266. private void OnVoidOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  267. {
  268. voidOverloadResult = "Void Overload called";
  269. Overload(101);
  270. }
  271. public void Overload(int number)
  272. {
  273. base.Call("Overload", OnIntOverload_Done, number);
  274. }
  275. private void OnIntOverload_Done(Hub hub, ClientMessage originalMessage, ResultMessage result)
  276. {
  277. intOverloadResult = string.Format("Overload with return value called => {0}", result.ReturnValue.ToString());
  278. }
  279. #endregion
  280. public void ReadStateValue()
  281. {
  282. base.Call("readStateValue", (hub, msg, result) => readStateResult = string.Format("Read some state! => {0}", result.ReturnValue));
  283. }
  284. public void PlainTask()
  285. {
  286. base.Call("plainTask", (hub, msg, result) => plainTaskResult = "Plain Task Result");
  287. }
  288. public void GenericTaskWithContinueWith()
  289. {
  290. base.Call("genericTaskWithContinueWith", (hub, msg, result) => genericTaskWithContinueWithResult = result.ReturnValue.ToString());
  291. }
  292. #endregion
  293. #region Server Called Functions
  294. private void FromArbitraryCode(Hub hub, MethodCallMessage methodCall)
  295. {
  296. fromArbitraryCodeResult = methodCall.Arguments[0] as string;
  297. }
  298. private void GroupAdded(Hub hub, MethodCallMessage methodCall)
  299. {
  300. if (!string.IsNullOrEmpty(groupAddedResult))
  301. groupAddedResult = "Group Already Added!";
  302. else
  303. groupAddedResult = "Group Added!";
  304. }
  305. private void Signal(Hub hub, MethodCallMessage methodCall)
  306. {
  307. dynamicTaskResult = string.Format("The dynamic task! {0}", methodCall.Arguments[0]);
  308. }
  309. private void Invoke(Hub hub, MethodCallMessage methodCall)
  310. {
  311. invokeResults.Add(string.Format("{0} client state index -> {1}", methodCall.Arguments[0], this.State["index"]));
  312. }
  313. #endregion
  314. #region Draw
  315. /// <summary>
  316. /// Display the result's of the function calls.
  317. /// </summary>
  318. public void Draw()
  319. {
  320. GUILayout.Label("Arbitrary Code");
  321. GUILayout.BeginHorizontal();
  322. GUILayout.Space(20);
  323. GUILayout.Label(string.Format("Sending {0} from arbitrary code without the hub itself!", fromArbitraryCodeResult));
  324. GUILayout.EndHorizontal();
  325. GUILayout.Space(10);
  326. GUILayout.Label("Group Added");
  327. GUILayout.BeginHorizontal();
  328. GUILayout.Space(20);
  329. GUILayout.Label(groupAddedResult);
  330. GUILayout.EndHorizontal();
  331. GUILayout.Space(10);
  332. GUILayout.Label("Dynamic Task");
  333. GUILayout.BeginHorizontal();
  334. GUILayout.Space(20);
  335. GUILayout.Label(dynamicTaskResult);
  336. GUILayout.EndHorizontal();
  337. GUILayout.Space(10);
  338. GUILayout.Label("Report Progress");
  339. GUILayout.BeginHorizontal();
  340. GUILayout.Space(20);
  341. GUILayout.BeginVertical();
  342. GUILayout.Label(longRunningJobStatus);
  343. GUILayout.HorizontalSlider(longRunningJobProgress, 0, 100);
  344. GUILayout.EndVertical();
  345. GUILayout.EndHorizontal();
  346. GUILayout.Space(10);
  347. GUILayout.Label("Generic Task");
  348. GUILayout.BeginHorizontal();
  349. GUILayout.Space(20);
  350. GUILayout.Label(genericTaskResult);
  351. GUILayout.EndHorizontal();
  352. GUILayout.Space(10);
  353. GUILayout.Label("Task With Exception");
  354. GUILayout.BeginHorizontal();
  355. GUILayout.Space(20);
  356. GUILayout.Label(taskWithExceptionResult);
  357. GUILayout.EndHorizontal();
  358. GUILayout.Space(10);
  359. GUILayout.Label("Generic Task With Exception");
  360. GUILayout.BeginHorizontal();
  361. GUILayout.Space(20);
  362. GUILayout.Label(genericTaskWithExceptionResult);
  363. GUILayout.EndHorizontal();
  364. GUILayout.Space(10);
  365. GUILayout.Label("Synchronous Exception");
  366. GUILayout.BeginHorizontal();
  367. GUILayout.Space(20);
  368. GUILayout.Label(synchronousExceptionResult);
  369. GUILayout.EndHorizontal();
  370. GUILayout.Space(10);
  371. GUILayout.Label("Invoking hub method with dynamic");
  372. GUILayout.BeginHorizontal();
  373. GUILayout.Space(20);
  374. GUILayout.Label(invokingHubMethodWithDynamicResult);
  375. GUILayout.EndHorizontal();
  376. GUILayout.Space(10);
  377. GUILayout.Label("Simple Array");
  378. GUILayout.BeginHorizontal();
  379. GUILayout.Space(20);
  380. GUILayout.Label(simpleArrayResult);
  381. GUILayout.EndHorizontal();
  382. GUILayout.Space(10);
  383. GUILayout.Label("Complex Type");
  384. GUILayout.BeginHorizontal();
  385. GUILayout.Space(20);
  386. GUILayout.Label(complexTypeResult);
  387. GUILayout.EndHorizontal();
  388. GUILayout.Space(10);
  389. GUILayout.Label("Complex Array");
  390. GUILayout.BeginHorizontal();
  391. GUILayout.Space(20);
  392. GUILayout.Label(complexArrayResult);
  393. GUILayout.EndHorizontal();
  394. GUILayout.Space(10);
  395. GUILayout.Label("Overloads");
  396. GUILayout.BeginHorizontal();
  397. GUILayout.Space(20);
  398. GUILayout.BeginVertical();
  399. GUILayout.Label(voidOverloadResult);
  400. GUILayout.Label(intOverloadResult);
  401. GUILayout.EndVertical();
  402. GUILayout.EndHorizontal();
  403. GUILayout.Space(10);
  404. GUILayout.Label("Read State Value");
  405. GUILayout.BeginHorizontal();
  406. GUILayout.Space(20);
  407. GUILayout.Label(readStateResult);
  408. GUILayout.EndHorizontal();
  409. GUILayout.Space(10);
  410. GUILayout.Label("Plain Task");
  411. GUILayout.BeginHorizontal();
  412. GUILayout.Space(20);
  413. GUILayout.Label(plainTaskResult);
  414. GUILayout.EndHorizontal();
  415. GUILayout.Space(10);
  416. GUILayout.Label("Generic Task With ContinueWith");
  417. GUILayout.BeginHorizontal();
  418. GUILayout.Space(20);
  419. GUILayout.Label(genericTaskWithContinueWithResult);
  420. GUILayout.EndHorizontal();
  421. GUILayout.Space(10);
  422. GUILayout.Label("Message Pump");
  423. GUILayout.BeginHorizontal();
  424. GUILayout.Space(20);
  425. invokeResults.Draw(Screen.width - 40, 270);
  426. GUILayout.EndHorizontal();
  427. GUILayout.Space(10);
  428. }
  429. #endregion
  430. }
  431. }
  432. #endif