Last active
June 24, 2016 19:06
-
-
Save jarroda/822358918af62d3f61dd04f6769ad84d to your computer and use it in GitHub Desktop.
Example of a projection based on aggregate relation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class MartenProjectionEx<T> : IProjection where T : class, new() | |
| { | |
| private readonly IAggregationFinder<T> _finder; | |
| private readonly IAggregator<T> _aggregator; | |
| private readonly Dictionary<Type, Func<object, Guid>> _relatedEvents = new Dictionary<Type, Func<object, Guid>>(); | |
| private readonly ProjectionOptions _options; | |
| public MartenProjectionEx(IAggregationFinder<T> finder, IAggregator<T> aggregator, ProjectionOptions options) | |
| { | |
| _finder = finder; | |
| _aggregator = aggregator; | |
| _options = options; | |
| } | |
| public void Apply(IDocumentSession session, EventStream[] streams) | |
| { | |
| foreach(var stream in streams.Where(_aggregator.AppliesTo)) | |
| { | |
| var related = stream.Events | |
| .Select(e => e.Data) | |
| .FirstOrDefault(e => _options._relatedEvents.ContainsKey(e.GetType())); | |
| T state; | |
| if (related != null) | |
| { | |
| var id = _options._relatedEvents[related.GetType()](related); | |
| state = session.Load<T>(id); | |
| } | |
| else | |
| { | |
| state = _finder.Find(stream, session); | |
| } | |
| update(state, stream); | |
| session.Store(state); | |
| }; | |
| } | |
| public Task ApplyAsync(IDocumentSession session, EventStream[] streams, CancellationToken token) | |
| { | |
| throw new NotImplementedException(); | |
| } | |
| private void update(T state, EventStream stream) | |
| { | |
| foreach (var e in stream.Events) | |
| { | |
| e.Apply(state, _aggregator); | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// ProjectionOptions supplies the configuration necessary | |
| /// for building a projection | |
| /// </summary> | |
| public class ProjectionOptions | |
| { | |
| internal readonly Dictionary<Type, Func<object, Guid>> _relatedEvents = new Dictionary<Type, Func<object, Guid>>(); | |
| public void ConfigureRelation<TEvent>(Expression<Func<TEvent, Guid>> expression) | |
| { | |
| var eventParam = Expression.Parameter(typeof(object), "evnt"); | |
| var idParam = Expression.Parameter(typeof(Guid), "id"); | |
| var convert = Expression.Convert(eventParam, typeof(TEvent)); | |
| var invoke = Expression.Invoke(expression, convert); | |
| var func = Expression.Lambda<Func<object, Guid>>(invoke, eventParam).Compile(); | |
| _relatedEvents[typeof(TEvent)] = func; | |
| } | |
| public void ConfigureRelation<TEvent, TAggregate>(Expression<Func<TAggregate, Guid>> expression) | |
| { | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment