PageRenderTime 42ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Bifrost/Events/EventSource.cs

#
C# | 167 lines | 102 code | 31 blank | 34 comment | 7 complexity | b43ac6fda56705cc6571b53b50937525 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.Linq.Expressions;
  24. using Bifrost.Lifecycle;
  25. namespace Bifrost.Events
  26. {
  27. /// <summary>
  28. /// Represents a <see cref="IEventSource">IEventSource</see>
  29. ///
  30. /// This is a base abstract class for any EventSource
  31. /// </summary>
  32. public abstract class EventSource : IEventSource, IUnitOfWork
  33. {
  34. /// <summary>
  35. /// Initializes an instance of <see cref="EventSource">EventSource</see>
  36. /// </summary>
  37. /// <param name="id">Id of the event source</param>
  38. protected EventSource(Guid id)
  39. {
  40. Id = id;
  41. UncommittedEvents = new UncommittedEventStream(id);
  42. }
  43. #pragma warning disable 1591 // Xml Comments
  44. public Guid Id { get; set; }
  45. public EventSourceVersion Version { get; private set; }
  46. public UncommittedEventStream UncommittedEvents { get; private set; }
  47. public void Apply(IEvent @event)
  48. {
  49. Apply(@event, true);
  50. }
  51. public void Apply(Expression<Action> expression)
  52. {
  53. var eventToApply = MethodEventFactory.CreateMethodEventFromExpression(Id, expression);
  54. Apply(eventToApply);
  55. }
  56. public virtual void ReApply(CommittedEventStream eventStream)
  57. {
  58. ValidateEventStream(eventStream);
  59. foreach (var @event in eventStream)
  60. ReApply(@event);
  61. Version = Version.NextCommit();
  62. }
  63. public void FastForward(EventSourceVersion lastVersion)
  64. {
  65. ThrowIfStateful();
  66. ThrowIfNotInitialVersion();
  67. Version = lastVersion.NextCommit();
  68. }
  69. public virtual void Commit()
  70. {
  71. UncommittedEvents = new UncommittedEventStream(Id);
  72. Version = Version.NextCommit();
  73. }
  74. public virtual void Rollback()
  75. {
  76. UncommittedEvents = new UncommittedEventStream(Id);
  77. Version = Version.PreviousCommit();
  78. }
  79. public void Dispose()
  80. {
  81. Commit();
  82. }
  83. #pragma warning restore 1591 // Xml Comments
  84. /// <summary>
  85. /// Get the aggregated root type
  86. /// </summary>
  87. protected virtual Type AggregatedRootType { get { return GetType(); } }
  88. /// <summary>
  89. /// Get the event source type
  90. /// </summary>
  91. protected virtual Type EventSourceType { get { return GetType(); } }
  92. void ReApply(IEvent @event)
  93. {
  94. Apply(@event, false);
  95. }
  96. void Apply(IEvent @event, bool isNew)
  97. {
  98. if (isNew)
  99. {
  100. @event.AggregatedRoot = AggregatedRootType.AssemblyQualifiedName;
  101. @event.EventSourceName = EventSourceType.AssemblyQualifiedName;
  102. UncommittedEvents.Append(@event);
  103. Version = Version.NextSequence();
  104. @event.Version = Version;
  105. }
  106. HandleInternally(@event);
  107. }
  108. void HandleInternally(IEvent @event)
  109. {
  110. var handleMethod = this.GetHandleMethod(@event);
  111. if (handleMethod != null)
  112. handleMethod.Invoke(this, new[] { @event });
  113. Version = @event.Version;
  114. }
  115. void ValidateEventStream(EventStream eventStream)
  116. {
  117. if (!IsForThisEventSource(eventStream.EventSourceId))
  118. throw new InvalidOperationException("Cannot apply an EventStream belonging to a different event source." +
  119. string.Format(@"Expected events for Id {0} but got events for Id {1}", Id, eventStream.EventSourceId));
  120. }
  121. bool IsForThisEventSource(Guid targetEventSourceId)
  122. {
  123. return targetEventSourceId == Id;
  124. }
  125. void ThrowIfStateful()
  126. {
  127. if (!this.IsStateless())
  128. throw new InvalidFastForwardException(ExceptionStrings.CannotFastForwardStatefulEventSource);
  129. }
  130. void ThrowIfNotInitialVersion()
  131. {
  132. if (!Version.Equals(EventSourceVersion.Zero))
  133. throw new InvalidFastForwardException(ExceptionStrings.CannotFastForwardEventSourceThatIsNotInitialVersion);
  134. }
  135. }
  136. }