public static void ValidateForPersistence(this AggregateRootType aggregateRootType) { if (aggregateRootType.NaturalKey == null) { throw new RuntimeException( string.Format( CultureInfo.InvariantCulture, @"The aggregate root of type '{0}' does not have a natural key defined. To fix this issue, either: - use a bootstrapper to define a natural key, or - decorate the natural key property on the aggregate root with the [dddlib.NaturalKey] attribute.", aggregateRootType.RuntimeType)) { HelpLink = "https://github.com/dddlib/dddlib/wiki/Aggregate-Root-Equality", }; } if (aggregateRootType.UninitializedFactory == null) { throw new RuntimeException( string.Format( CultureInfo.InvariantCulture, @"The aggregate root of type '{0}' does not have a factory method registered with the runtime. To fix this issue, either: - use a bootstrapper to register a factory method with the runtime, or - add a default constructor to the aggregate root.", aggregateRootType.RuntimeType)) { HelpLink = "https://github.com/dddlib/dddlib/wiki/Aggregate-Root-Reconstitution", }; } }
public override int GetHashCode() { unchecked { return((AggregateRootType.GetHashCode() * 397) ^ AggregateRootId.GetHashCode()); } }
public ICollection <IProjectionEntry> GetEntries(AggregateRootType aggregateRootType) { Contract.Requires(aggregateRootType != null); Contract.Ensures(Contract.Result <ICollection <IProjectionEntry> >() != null); throw new NotImplementedException(); }
public AggregateRootType Create(Type type) { var entityType = default(EntityType); foreach (var subType in type.GetTypeHierarchyUntil(typeof(object)).Reverse()) { if (entityType == null) { entityType = new EntityType(subType, this.typeAnalyzerService); continue; } if (this.typeAnalyzerService.IsValidAggregateRoot(subType)) { break; } entityType = new EntityType(subType, this.typeAnalyzerService, entityType); } var aggregateRootType = default(AggregateRootType); foreach (var subType in type.GetTypeHierarchyUntil(typeof(Entity)).Reverse()) { aggregateRootType = new AggregateRootType(subType, this.typeAnalyzerService, aggregateRootType ?? entityType); } var configuration = new BootstrapperConfiguration(aggregateRootType, this.typeAnalyzerService); var bootstrapper = this.bootstrapperProvider.GetBootstrapper(type); bootstrapper.Invoke(configuration); return(aggregateRootType); }
public TypeInformation(AggregateRootType aggregateRootType) { Guard.Against.Null(() => aggregateRootType); this.EventDispatcher = aggregateRootType.EventDispatcher; this.PersistEvents = aggregateRootType.PersistEvents; }
public ISnapshotPolicy GetPolicy(AggregateRootType eventProviderType) { Contract.Requires(eventProviderType != null); Contract.Ensures(Contract.Result <ISnapshotPolicy>() != null); throw new NotImplementedException(); }
public ICollection <IProjectionManager> GetManagers(AggregateRootType aggregateRootType) { Contract.Requires(aggregateRootType != null); Contract.Ensures(Contract.Result <IEnumerable <IProjectionManager> >() != null); throw new NotImplementedException(); }
public void ApplicationCanCreateRuntimeTypeForValidType() { // arrange var type = typeof(Aggregate); var typeAnalyzerService = A.Fake <ITypeAnalyzerService>(o => o.Strict()); A.CallTo(() => typeAnalyzerService.IsValidAggregateRoot(type)).Returns(true); A.CallTo(() => typeAnalyzerService.IsValidEntity(type)).Returns(true); A.CallTo(() => typeAnalyzerService.GetNaturalKey(type)).Returns(null); A.CallTo(() => typeAnalyzerService.IsValidAggregateRoot(typeof(AggregateRoot))).Returns(true); A.CallTo(() => typeAnalyzerService.IsValidEntity(typeof(AggregateRoot))).Returns(true); A.CallTo(() => typeAnalyzerService.GetNaturalKey(typeof(AggregateRoot))).Returns(null); A.CallTo(() => typeAnalyzerService.IsValidEntity(typeof(Entity))).Returns(true); A.CallTo(() => typeAnalyzerService.GetNaturalKey(typeof(Entity))).Returns(null); var entityType = new EntityType(typeof(Entity), typeAnalyzerService); var aggregateType = new AggregateRootType(typeof(AggregateRoot), typeAnalyzerService, entityType); var expectedType = new AggregateRootType(type, typeAnalyzerService, aggregateType); var factory = A.Fake <Func <Type, AggregateRootType> >(o => o.Strict()); A.CallTo(() => factory.Invoke(type)).Returns(expectedType); using (new Application(factory, t => null, t => null)) { // act var actualType = Application.Current.GetAggregateRootType(type); // assert actualType.Should().Be(expectedType); } }
private void ExecuteDomainEvent(IMessage @event) { var eventType = @event.GetType(); var methodName = "OnDomainEvent"; var eventTypeFullName = @event.GetType(); var domainEventType = typeof(IDomainEvent); var aggregateTypeFullName = AggregateRootType.FullName; if (!domainEventType.IsAssignableFrom(eventType)) { throw new MethodNotFoundException($"The method: {methodName}({eventTypeFullName}) in {aggregateTypeFullName} is wrong, reason: {eventTypeFullName} cannot assign to interface: {domainEventType.FullName}."); } var method = AggregateRootType .GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public, null, new[] { eventType }, null); if (method == null) { throw new MethodNotFoundException($"No {methodName}({eventTypeFullName}) found in {aggregateTypeFullName}."); } var instance = Expression.Constant(this); var parameter = Expression.Parameter(eventType, methodName); var call = Expression.Call(instance, method, parameter); var lambda = Expression.Lambda(call, parameter); var methodDelegate = lambda.Compile(); methodDelegate.DynamicInvoke(@event); }
public AggregateRootConfigurationWrapper(AggregateRootType aggregateRootType, IEntityConfigurationWrapper <T> entityConfigurationWrapper) { Guard.Against.Null(() => aggregateRootType); Guard.Against.Null(() => entityConfigurationWrapper); this.aggregateRootType = aggregateRootType; this.entityConfigurationWrapper = entityConfigurationWrapper; }
public static void ThrowNotFound(this AggregateRootType aggregateRootType, object naturalKey) { throw new AggregateRootNotFoundException( string.Format( CultureInfo.InvariantCulture, "Cannot find the aggregate root of type '{0}' with natural key '{1}'.", aggregateRootType.RuntimeType, naturalKey)); }
public BootstrapperConfiguration(AggregateRootType aggregateRootType, ITypeAnalyzerService typeAnalyzerService) { Guard.Against.Null(() => aggregateRootType); Guard.Against.Null(() => typeAnalyzerService); this.aggregateRootType = aggregateRootType; this.entityType = aggregateRootType; this.typeAnalyzerService = typeAnalyzerService; }
public ProjectionEntry(AggregateRootType aggregateRootType, ProjectionType projectionType, IProjectionManager projectionManager) : this(aggregateRootType, projectionType, projectionManager.GetType()) { Contract.Requires(aggregateRootType != null); Contract.Requires(projectionType != null); Contract.Requires(projectionManager != null); ProjectionManager = projectionManager; }
private void ExecutingDomainCommand(AggregateRootMessagingContext context, IDomainCommand command) { var methodName = "OnDomainCommand"; var commandType = command.GetType(); var commandTypeFullName = command.GetType(); var domainCommandType = typeof(IDomainCommand); var aggregateTypeFullName = AggregateRootType.FullName; if (!domainCommandType.IsAssignableFrom(commandType)) { throw new MethodNotFoundException($"The method: {methodName}({commandTypeFullName}) in {aggregateTypeFullName} is wrong, reason: {commandTypeFullName} cannot assign to interface: {domainCommandType.FullName}."); } var methodWithoutContext = AggregateRootType .GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public, null, new[] { commandType }, null); if (methodWithoutContext != null) { var instance = Expression.Constant(this); var parameter = Expression.Parameter(commandType, methodName); var call = Expression.Call(instance, methodWithoutContext, parameter); var lambda = Expression.Lambda(call, parameter); var methodDelegate = lambda.Compile(); methodDelegate.DynamicInvoke(command); return; } var contextType = context.GetType(); var methodWithContext = AggregateRootType .GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public, null, new[] { contextType, commandType }, null); if (methodWithContext != null) { var instance = Expression.Constant(this); var parameter1 = Expression.Parameter(contextType, $"{methodName}_0"); var parameter2 = Expression.Parameter(commandType, $"{methodName}_1"); var call = Expression.Call(instance, methodWithContext, parameter1, parameter2); var lambda = Expression.Lambda(call, parameter1, parameter2); var methodDelegate = lambda.Compile(); methodDelegate.DynamicInvoke(context, command); return; } throw new MethodNotFoundException($"No {methodName}({commandTypeFullName}) found in {aggregateTypeFullName}."); }
public ProjectionEntry(AggregateRootType aggregateRootType, ProjectionType projectionType, Type projectionManagerType) { Contract.Requires(aggregateRootType != null); Contract.Requires(projectionType != null); Contract.Requires(projectionManagerType != null); AggregateRootType = aggregateRootType; ProjectionType = projectionType; ProjectionManagerType = projectionManagerType; }
public ISnapshotProvider GetProvider(AggregateRootType eventProviderType) { ISnapshotProvider provider; if (_providers.TryGetValue(eventProviderType, out provider)) { return(provider); } return(null); }
private SqlCommand CreateSqlCommand(AggregateRootType aggregateRootType, AggregateRootIdentity identity) { var sqlCommand = new SqlCommand("[dbo].[GetDomainEvents]"); sqlCommand.CommandType = CommandType.StoredProcedure; // set parameters sqlCommand.Parameters.Add("@aggregateRootId", SqlDbType.UniqueIdentifier).Value = identity.Value; sqlCommand.Parameters.Add("@aggregateRootTypeId", SqlDbType.Binary, 16).Value = _typeFactory.GetHash(aggregateRootType.Type); return(sqlCommand); }
private SqlCommand CreateSqlCommand(AggregateRootType aggregateRootType, int skip, int take) { var sqlCommand = new SqlCommand("[dbo].[GetTransactionsByAggregateRootType]"); sqlCommand.CommandType = CommandType.StoredProcedure; // set parameters sqlCommand.Parameters.Add("@aggregateRootTypeId", SqlDbType.Binary, 16).Value = _typeFactory.GetHash(aggregateRootType.Type); sqlCommand.Parameters.Add("@skip", SqlDbType.Int).Value = skip; sqlCommand.Parameters.Add("@take", SqlDbType.Int).Value = take; return(sqlCommand); }
public static void Validate(this AggregateRootType aggregateRootType, object naturalKey) { if (aggregateRootType.NaturalKey.PropertyType != naturalKey.GetType()) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, "Invalid natural key value type for aggregate root of type '{0}'. Expected value type of '{1}' but value is type of '{2}'.", aggregateRootType.RuntimeType, aggregateRootType.NaturalKey.PropertyType, naturalKey.GetType()), Guard.Expression.Parse(() => naturalKey)); } }
public static object GetNaturalKey(this AggregateRootType aggregateRootType, AggregateRoot aggregateRoot) { var naturalKey = aggregateRootType.NaturalKey.GetValue(aggregateRoot); if (naturalKey == null) { // NOTE (Cameron): This mimics the Guard clause functionality by design. throw new ArgumentException( "Value cannot be null.", string.Concat(Guard.Expression.Parse(() => aggregateRoot), ".", aggregateRootType.NaturalKey.PropertyName)); } return(naturalKey); }
protected override async Task <EventStream> GetEventStreamAsync(AggregateRootType eventProviderType, AggregateRootIdentity identity) { // establish command var command = new GetDomainEventsCommand(_serializer, _typeFactory, eventProviderType, identity); // create connection using (var conn = new SqlConnection(_connectionString)) { // connection needs to be open before executing await conn.OpenAsync(); // execute return(await command.ExecuteAsync(conn)); } }
public GetDomainEventsCommand(SqlSerializer serializer, ITypeFactory typeFactory, AggregateRootType aggregateRootType, AggregateRootIdentity aggregateRootIdentity) { Contract.Requires(serializer != null); Contract.Requires(aggregateRootType != null); Contract.Requires(typeFactory != null); Contract.Requires(aggregateRootIdentity != null); _serializer = serializer; _typeFactory = typeFactory; _aggregateRootType = aggregateRootType; _aggregateRootIdentity = aggregateRootIdentity; _command = CreateSqlCommand(aggregateRootType, aggregateRootIdentity); }
public GetTransactionsByAggregateRootTypeCommand(SqlSerializer serializer, ITypeFactory typeFactory, AggregateRootType aggregateRootType, int skip, int take) { Contract.Requires(serializer != null); Contract.Requires(aggregateRootType != null); Contract.Requires(typeFactory != null); _serializer = serializer; _typeFactory = typeFactory; _aggregateRootType = aggregateRootType; _sqlDomainEvents = new Collection <SqlDomainEvent>(); _revisions = new Collection <SqlRevision>(); _command = CreateSqlCommand(aggregateRootType, skip, take); }
public ICollection <IProjectionManager> GetManagers(AggregateRootType aggregateRootType) { var managers = new Collection <IProjectionManager>(); // loop through all entries in catalog to retrieve projection managers foreach (var entry in Catalog.GetEntries(aggregateRootType)) { Contract.Assume(entry != null); var manager = GetManager(entry); if (manager == null) { continue; } managers.Add(manager); } // return managers return(managers); }
public void AddProvider(AggregateRootType eventProviderType, ISnapshotProvider snapshotProvider) { _providers.Add(eventProviderType, snapshotProvider); Contract.Assume(GetProvider(eventProviderType) == snapshotProvider); }
/// <summary> /// Initializes a new instance of the <see cref="AggregateRoot"/> class. /// </summary> /// <param name="aggregateRootType">The aggregate root type.</param> protected AggregateRoot(AggregateRootType aggregateRootType) : this(@this => new TypeInformation(aggregateRootType)) { }
public override int GetHashCode() { return(AggregateRootType.GetHashCode() + EventType.GetHashCode()); }
public ISnapshotProvider GetProvider(AggregateRootType eventProviderType) { Contract.Requires(eventProviderType != null); throw new NotImplementedException(); }
public void AddProvider(AggregateRootType eventProviderType, ISnapshotProvider snapshotProvider) { Contract.Requires(eventProviderType != null); Contract.Requires(snapshotProvider != null); Contract.Ensures(GetProvider(eventProviderType) != null); }
public ICollection <IProjectionEntry> GetEntries(AggregateRootType aggregateRootType) { return(_entries.Where(x => x.AggregateRootType == aggregateRootType).ToList()); }