PageRenderTime 84ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Bifrost/Sagas/SagaConverter.cs

#
C# | 167 lines | 113 code | 26 blank | 28 comment | 13 complexity | b089af8e34d4a17b5b8d7d53a163f9aa MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. #region License
  2. //
  3. // Copyright (c) 2008-2012, DoLittle Studios and Komplett ASA
  4. //
  5. // Licensed under the Microsoft Permissive License (Ms-PL), Version 1.1 (the "License")
  6. // With one exception :
  7. // Commercial libraries that is based partly or fully on Bifrost and is sold commercially,
  8. // must obtain a commercial license.
  9. //
  10. // You may not use this file except in compliance with the License.
  11. // You may obtain a copy of the license at
  12. //
  13. // http://bifrost.codeplex.com/license
  14. //
  15. // Unless required by applicable law or agreed to in writing, software
  16. // distributed under the License is distributed on an "AS IS" BASIS,
  17. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. // See the License for the specific language governing permissions and
  19. // limitations under the License.
  20. //
  21. #endregion
  22. using System;
  23. using System.Collections.Generic;
  24. using System.Linq;
  25. using Bifrost.Events;
  26. using Bifrost.Execution;
  27. using Bifrost.Serialization;
  28. namespace Bifrost.Sagas
  29. {
  30. /// <summary>
  31. /// Represents a <see cref="ISagaConverter"/>
  32. /// </summary>
  33. public class SagaConverter : ISagaConverter
  34. {
  35. static readonly string[] SagaProperties = typeof(ISaga).GetProperties().Select(t => t.Name).ToArray();
  36. static readonly SerializationOptions SerializationOptions =
  37. new SerializationOptions
  38. {
  39. ShouldSerializeProperty = (t, p) =>
  40. {
  41. if (typeof (ISaga).IsAssignableFrom(t))
  42. return !SagaProperties.Any(sp => sp == p);
  43. return true;
  44. }
  45. };
  46. readonly IContainer _container;
  47. readonly IEventConverter _eventConverter;
  48. readonly ISerializer _serializer;
  49. /// <summary>
  50. /// Initializes a new instance of <see cref="SagaConverter"/>
  51. /// </summary>
  52. /// <param name="container">A <see cref="IContainer"/> for creating instances of types</param>
  53. /// <param name="eventConverter">A <see cref="IEventConverter"/> for converting any <see cref="IEvent">events</see> in a <see cref="ISaga"/></param>
  54. /// <param name="serializer">A <see cref="ISerializer"/> to use for serialization</param>
  55. public SagaConverter(IContainer container, IEventConverter eventConverter, ISerializer serializer)
  56. {
  57. _container = container;
  58. _eventConverter = eventConverter;
  59. _serializer = serializer;
  60. }
  61. #pragma warning disable 1591 // Xml Commentsz
  62. public ISaga ToSaga(SagaHolder sagaHolder)
  63. {
  64. if (string.IsNullOrEmpty(sagaHolder.Type))
  65. return null;
  66. var type = Type.GetType(sagaHolder.Type);
  67. Type currentChapterType = null;
  68. if (!string.IsNullOrEmpty(sagaHolder.CurrentChapterType))
  69. currentChapterType = Type.GetType(sagaHolder.CurrentChapterType);
  70. ISaga saga;
  71. if (string.IsNullOrEmpty(sagaHolder.SerializedSaga))
  72. saga = _container.Get(type) as ISaga;
  73. else
  74. saga = (ISaga) _serializer.FromJson(type,sagaHolder.SerializedSaga, SerializationOptions);
  75. saga.Id = sagaHolder.Id;
  76. saga.Partition = sagaHolder.Partition;
  77. saga.Key = sagaHolder.Key;
  78. saga.CurrentState = sagaHolder.State;
  79. if (!string.IsNullOrEmpty(sagaHolder.UncommittedEvents))
  80. {
  81. var uncommittedEvents = new List<EventHolder>();
  82. _serializer.FromJson(uncommittedEvents,sagaHolder.UncommittedEvents);
  83. var actualEvents = _eventConverter.ToEvents(uncommittedEvents);
  84. saga.SetUncommittedEvents(actualEvents);
  85. }
  86. DeserializeChapters(sagaHolder, saga, currentChapterType);
  87. return saga;
  88. }
  89. public SagaHolder ToSagaHolder(ISaga saga)
  90. {
  91. var sagaHolder = new SagaHolder();
  92. Populate(sagaHolder, saga);
  93. return sagaHolder;
  94. }
  95. public void Populate(SagaHolder sagaHolder, ISaga saga)
  96. {
  97. sagaHolder.Id = saga.Id;
  98. sagaHolder.Name = saga.GetType().Name;
  99. sagaHolder.Type = saga.GetType().AssemblyQualifiedName;
  100. sagaHolder.Key = saga.Key;
  101. sagaHolder.Partition = saga.Partition;
  102. sagaHolder.State = saga.CurrentState.ToString();
  103. sagaHolder.SerializedSaga = _serializer.ToJson(saga, SerializationOptions);
  104. sagaHolder.UncommittedEvents = _serializer.ToJson(_eventConverter.ToEventHolders(saga.GetUncommittedEvents()));
  105. var chapterHolders = (from c in saga.Chapters
  106. select GetChapterHolderFromChapter(c)).ToArray();
  107. sagaHolder.SerializedChapters = _serializer.ToJson(chapterHolders);
  108. if (saga.CurrentChapter != null)
  109. sagaHolder.CurrentChapterType = saga.CurrentChapter.GetType().AssemblyQualifiedName;
  110. }
  111. #pragma warning restore 1591 // Xml Comments
  112. ChapterHolder GetChapterHolderFromChapter(IChapter chapter)
  113. {
  114. var chapterHolder = new ChapterHolder
  115. {
  116. Type = chapter.GetType().AssemblyQualifiedName,
  117. SerializedChapter = _serializer.ToJson(chapter)
  118. };
  119. return chapterHolder;
  120. }
  121. void DeserializeChapters(SagaHolder sagaHolder, ISaga saga, Type currentChapterType)
  122. {
  123. if (!string.IsNullOrEmpty(sagaHolder.SerializedChapters))
  124. {
  125. var chapterHolders = new List<ChapterHolder>();
  126. _serializer.FromJson(chapterHolders,sagaHolder.SerializedChapters);
  127. foreach (var chapterHolder in chapterHolders)
  128. {
  129. var chapterType = Type.GetType(chapterHolder.Type);
  130. var chapter = _container.Get(chapterType) as IChapter;
  131. if (!string.IsNullOrEmpty(chapterHolder.SerializedChapter))
  132. _serializer.FromJson(chapter, chapterHolder.SerializedChapter);
  133. saga.AddChapter(chapter);
  134. if (currentChapterType != null &&
  135. chapterType == currentChapterType)
  136. saga.SetCurrentChapter(chapter);
  137. }
  138. }
  139. }
  140. }
  141. }