Пример #1
0
        public static void MapAggregate(IBoundedContextModel contextMap, Type aggregateType)
        {
            var methods = aggregateType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);

            foreach (var method in methods)
            {
                var parameters = method.GetParameters();

                if (parameters.Count() == 1 &&
                    parameters[0].ParameterType.Namespace != null &&
                    parameters[0].ParameterType.Namespace.StartsWith(aggregateType.Namespace) &&
                    method.Name == "When")
                {
                    if (methods.Any(m => m.Name == "Then" && m.GetParameters().FirstOrDefault(p => p.ParameterType == method.ReturnType) != null))
                    {
                        CallGenericMethod(nameof(ApplyCommandHandlerToContextMap), contextMap, aggregateType, method.ReturnType, parameters);
                    }
                    else
                    {
                        var eventTypes = methods.Where(m => m.Name == "Then" && m.GetParameters().Count() == 1).Select(m => m.GetParameters().Single().ParameterType);

                        var returnTypeProperties = method.ReturnType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

                        if (returnTypeProperties.All(p => eventTypes.Contains(p.PropertyType)))
                        {
                            returnTypeProperties.Select(p => p.PropertyType).ToList().ForEach(t => CallGenericMethod(nameof(ApplyCommandHandlerToContextMap), contextMap, aggregateType, t, parameters));
                        }
                    }
                }
            }
        }
Пример #2
0
 /// <summary>
 /// Eventhandlers are identified by not being aggregates and having method(s):
 /// named When
 /// with a single parameter that is a known event type and returns a command
 /// </summary>
 /// <param name="publicTypes"></param>
 public static void MapEventHandlers(IBoundedContextModel contextMap, IEnumerable <Type> publicTypes)
 {
     foreach (var publicType in publicTypes)
     {
         MapEventHandler(contextMap, publicType);
     }
 }
Пример #3
0
 /// <summary>
 /// Creates a new instance of a domain engine for processing commands and optionly event handlers from a single bounded context.  By default the engine will process a command
 /// handler & aggregate root for a command and return any events generated by the aggregate.
 /// </summary>
 /// <param name="boundedContextModel">Describes the static model of the domain.  Include the command handlers and any event handlers to be executed in process.</param>
 /// <param name="eventStore">The event store used for event persistence by both command and event handers.</param>
 /// <param name="options">Options relating to the domain engine exection.</param>
 public DomainEngine(IBoundedContextModel boundedContextModel, IEventStore eventStore, DomainOptions options)
 {
     this.boundedContextModel = boundedContextModel;
     this.runtimeModel        = new RuntimeModel(boundedContextModel, eventStore);
     this.commandHandler      = new CommandHandler(boundedContextModel, runtimeModel);
     this.domainOptions       = options;
 }
Пример #4
0
 /// <summary>
 /// Aggregates are identified by having method(s) that:
 /// are named "When"
 /// have a single parameter
 /// with a type from the same or child namespace
 /// and a matching method named Then whos parameter is the same as the return type of the When method
 /// </summary>
 public static void MapAggregates(IBoundedContextModel contextMap, IEnumerable <Type> publicTypes)
 {
     foreach (var publicType in publicTypes)
     {
         MapAggregate(contextMap, publicType);
     }
 }
Пример #5
0
        /// <summary>
        /// Creates a domin execution instance that can fully process command handlers and any configured event handlers
        /// including recursive handling of any commands generated by process managers.
        /// </summary>
        /// <param name="boundedContextModel">Describes the static model of the domain.  Include the command handlers and any event handlers to be executed in process.</param>
        /// <param name="eventStore">The event store used for event persistence by both command and event handers.</param>
        /// <param name="eventQueueWriter">An event sink for writing the event output to a queue or similiar from within the command processing transaction.</param>
        /// <param name="isRuntimeModelCached">Is the runtime moel cached between calls, only set this true for single instance deployments.</param>
        /// <returns>Domain inteface for processing commands.</returns>
        public static IDomainEngine CreateDomainExecutionEngine(IBoundedContextModel boundedContextModel, IEventStore eventStore, IEventQueueWriter eventQueueWriter, DomainOptions options)
        {
            return(new DomainEngine(boundedContextModel, eventStore, options).WithEventBroker().WithEventQueue(eventQueueWriter));

            //var domainEngine = new DomainExecutionEngine(boundedContextModel, eventStore).WithEventQueue(eventQueueWriter);
            //domainEngine.IsRuntimeModelCached = isRuntimeModelCached;
            //return domainEngine;
        }
        public static IBoundedContextModel WithAllAppDomainAssemblies(this IBoundedContextModel contextMap)
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            foreach (var assembly in assemblies.Where(a => !a.IsDynamic))
            {
                contextMap.WithAssembly(assembly, null);
            }

            return(contextMap);
        }
        public static IBoundedContextModel WithAssembly(this IBoundedContextModel contextMap, Assembly assembly, string contextNamespace)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            AutoConfigure.FromAssembly(contextMap, assembly, contextNamespace);

            return(contextMap);
        }
        public static IBoundedContextModel WithAssembly(this IBoundedContextModel contextMap, string assemblyName, string contextNamespace = null)
        {
            var assembly = Assembly.Load(assemblyName);

            if (assembly.IsDynamic)
            {
                throw new ArgumentException("Dynamic assemblies are not supported.");
            }

            contextMap.WithAssembly(assembly, contextNamespace);

            return(contextMap);
        }
Пример #9
0
        public static void FromAssembly(IBoundedContextModel contextMap, Assembly assembly, string contextNamespace)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            var publicTypes = contextNamespace == null?assembly.GetExportedTypes() : assembly.GetExportedTypes().Where(t => t.Namespace.StartsWith(contextNamespace));

            AutoConfigure.MapAggregates(contextMap, publicTypes);

            var allPublicTypesExceptAggregates = publicTypes.Where(t => !contextMap.IsAggregateType(t)).Distinct();

            AutoConfigure.MapEventHandlers(contextMap, allPublicTypesExceptAggregates);
        }
Пример #10
0
        private static void CallGenericMethod(string methodName, IBoundedContextModel contextMap, Type publicType, Type returnType, ParameterInfo[] parameters)
        {
            MethodInfo applyToContextMapInfo = typeof(AutoConfigure).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic);

            MethodInfo genericMethod;

            if (returnType == typeof(void))
            {
                genericMethod = applyToContextMapInfo.MakeGenericMethod(parameters[0].ParameterType, publicType);
            }
            else
            {
                genericMethod = applyToContextMapInfo.MakeGenericMethod(parameters[0].ParameterType, publicType, returnType);
            }

            genericMethod.Invoke(null, new object[] { contextMap });
        }
Пример #11
0
        public static void MapEventHandler(IBoundedContextModel contextMap, Type eventHandlerType)
        {
            var methods = eventHandlerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);

            foreach (var method in methods.Where(m => m.Name == "When"))
            {
                var parameters = method.GetParameters();

                if (parameters.Count() == 1 && contextMap.IsEventType(parameters[0].ParameterType))
                {
                    if (method.ReturnType != null && contextMap.IsCommandType(method.ReturnType))
                    {
                        CallGenericMethod(nameof(ApplyProcessHandlerToContextMap), contextMap, eventHandlerType, method.ReturnType, parameters);
                    }
                    else
                    {
                        CallGenericMethod(nameof(ApplyEventHandlerToContextMap), contextMap, eventHandlerType, typeof(void), parameters);
                    }
                }
            }
        }
Пример #12
0
        public DomainBroker(IBoundedContextModel boundedContextModel, IEventHandler eventHandler, ICommandHandler commandHandler)
        {
            if (boundedContextModel == null)
            {
                throw new ArgumentNullException(nameof(boundedContextModel));
            }

            if (eventHandler == null)
            {
                throw new ArgumentNullException(nameof(eventHandler));
            }

            if (commandHandler == null)
            {
                throw new ArgumentNullException(nameof(commandHandler));
            }

            this.boundedContextModel = boundedContextModel;
            this.eventHandler        = eventHandler;
            this.commandHandler      = commandHandler;
        }
Пример #13
0
 /// <summary>
 /// Creates a domain command engine that processes command handlers and returns any events created.
 /// </summary>
 /// <param name="boundedContextModel">Describes the static model of the domain.  Any defined event handlers will be ignored.</param>
 /// <param name="eventStore">The event store used for event persistence by command handlers.</param>
 /// <returns>Domain inteface for processing commands.</returns>
 public static IDomainEngine CreateCommandEngine(IBoundedContextModel boundedContextModel, IEventStore eventStore)
 {
     return(new DomainEngine(boundedContextModel, eventStore, DomainOptions.Defaults));
 }
Пример #14
0
 /// <summary>
 /// Created a dispatcher for domain events that can one way dispatch events to any defined event handlers.
 /// </summary>
 /// <param name="boundedContextModel">Describes the static model of the domain.  Only event handler definitions are used for determining the event handlers that need to b e called.</param>
 /// <param name="eventHandler">The event handler instance to receive events.  This will be called once per event for each defined event handler.</param>
 /// <returns>Domain inteface for dispatching events.</returns>
 public static IEventDispatcher CreateEventDispatcher(IBoundedContextModel boundedContextModel, IEventHandler eventHandler)
 {
     return(new EventDispatcher(boundedContextModel, eventHandler));
 }
Пример #15
0
 public CommandHandler(IBoundedContextModel contextModel, IRuntimeModel runtimeModel)
 {
     this.contextModel = contextModel;
     this.runtimeModel = runtimeModel;
 }
Пример #16
0
 public EventHandlerAdapter(TEventHandler eventHandler, IBoundedContextModel contextMap)
 {
     this.eventHandler      = eventHandler;
     this.contextMap        = contextMap;
     this.eventHandlerModel = this.contextMap.EventHandlerModel(typeof(TEventHandler));
 }
Пример #17
0
 /// <summary>
 /// Creates a domain event engine for processing an event handler.
 /// </summary>
 /// <param name="boundedContextModel">Describes the static model of the domain.  Only event handler definitions are used for the processing of events.</param>
 /// <param name="eventStore">The event store used to store any events handled by event handlers to ensure idempotency.</param>
 /// <returns>Domain inteface for processing events.</returns>
 public static IEventHandler CreateEventHandler(IBoundedContextModel boundedContextModel, IEventStore eventStore)
 {
     return(new TransactionalEventHandler(boundedContextModel, eventStore, cacheRuntimeModel: false));
 }
Пример #18
0
 private static void ApplyEventHandlerToContextMap <TEvent, TEventHandler>(IBoundedContextModel contextMap) where TEventHandler : class
 {
     contextMap.WithEventHandler <TEvent, TEventHandler>((e) => e.Id);
 }
Пример #19
0
 internal AggregateAdapter(IBoundedContextModel contextMap, TAggregateRoot aggregateRoot, int version)
     : this(contextMap, aggregateRoot)
 {
     this.version = version;
 }
 public IEventHandlerAdapter <TProcess> CreateEventHandler <TProcess>(string id, TProcess process, IBoundedContextModel contextMap)
 {
     return(new EventHandlerAdapter <TProcess>(process, contextMap).WithId(id));
 }
Пример #21
0
 public RuntimeAggregateModel(IBoundedContextModel contextMap, IEventStore eventStore)
 {
     this.contextMap         = contextMap;
     this.eventStore         = eventStore;
     this.snapshotRepository = eventStore as ISnapshotRepository;
 }
Пример #22
0
 public IAggregateAdapter <TAggregate> CreateAggregate <TAggregate>(IBoundedContextModel contextMap, TAggregate aggregate, int version)
 {
     return(new AggregateAdapter <TAggregate>(contextMap, aggregate, version));
 }
 internal TransactionalEventHandler(IBoundedContextModel boundedContextModel, IEventStore eventStore, bool cacheRuntimeModel)
 {
     this.runtimeModel      = new RuntimeModel(boundedContextModel, eventStore);
     this.eventHandler      = new EventHandler(boundedContextModel, runtimeModel);
     this.cacheRuntimeModel = cacheRuntimeModel;
 }
Пример #24
0
 public EventDispatcher(IBoundedContextModel boundedContextModel, IEventHandler eventHandler)
 {
     this.boundedContextModel = boundedContextModel;
     this.eventHandler        = eventHandler;
 }
Пример #25
0
 public RuntimeModel(IBoundedContextModel contextMap, IEventStore eventStore)
 {
     this.aggregates    = new RuntimeAggregateModel(contextMap, eventStore);
     this.eventHandlers = new RuntimeEventHandlerModel(contextMap, eventStore);
 }
Пример #26
0
 private static void ApplyProcessHandlerToContextMap <TEvent, TEventHandler, TCommand>(IBoundedContextModel contextMap) where TEventHandler : class
 {
     contextMap.WithEventHandler <TEvent, TEventHandler, TCommand>((e) => e.Id, c => c.GetType().GetProperties().First().GetValue(c).ToString());
 }
Пример #27
0
 /// <summary>
 /// Creates a domain command engine for processing command handlers that returns any events created as well as passing them to any defined event
 /// handlers while within the same transaction scope.  It is the responsibility of the event handers to further dispatch any commands they raise.
 /// </summary>
 /// <param name="boundedContextModel">Describes the static model of the domain.  Event handler definitions are used to determine the event handlers to call.</param>
 /// <param name="eventStore">The event store used for event persistence by command handlers.</param>
 /// <param name="eventHandler">The event handler instance to receive events.  This will be called once per event for each defined event handler.</param>
 /// <returns>Domain inteface for processing commands.</returns>
 public static IDomainEngine CreateCommandEngine(IBoundedContextModel boundedContextModel, IEventStore eventStore, IEventHandler eventHandler)
 {
     return(new DomainEngine(boundedContextModel, eventStore, DomainOptions.Defaults).WithEventDispatcher(new EventDispatcher(boundedContextModel, eventHandler)));
 }
Пример #28
0
 internal AggregateAdapter(IBoundedContextModel contextMap, TAggregateRoot aggregateRoot)
 {
     this.contextMap     = contextMap;
     this.aggregateRoot  = aggregateRoot;
     this.aggregateModel = contextMap.AggregateModel(typeof(TAggregateRoot));
 }
Пример #29
0
 public RuntimeEventHandlerModel(IBoundedContextModel contextMap, IEventStore eventStore)
 {
     this.contextMap = contextMap;
     this.eventStore = eventStore;
 }
Пример #30
0
 private static void ApplyCommandHandlerToContextMap <TCommand, TAggregate, TEvent>(IBoundedContextModel contextMap)
 {
     contextMap.WithCommandHandler <TCommand, TAggregate, TEvent>();
 }