Skip to content

Commit 8b81644

Browse files
authored
Merge pull request #15 from XerProjects/release-4.0.0
Release 4.0.0
2 parents 7058cb9 + 25b3979 commit 8b81644

9 files changed

+195
-22
lines changed

Src/Xer.DomainDriven/DomainEventStream.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public DomainEventStream AppendDomainEvent(IDomainEvent domainEventToAppend)
7171
throw new ArgumentNullException(nameof(domainEventToAppend));
7272
}
7373

74-
if (!AggregateRootId.Equals(domainEventToAppend.AggregateRootId))
74+
if (AggregateRootId != domainEventToAppend.AggregateRootId)
7575
{
7676
throw new InvalidOperationException("Cannot append domain event belonging to a different aggregate root.");
7777
}
@@ -91,7 +91,7 @@ public DomainEventStream AppendDomainEventStream(IDomainEventStream streamToAppe
9191
throw new ArgumentNullException(nameof(streamToAppend));
9292
}
9393

94-
if (!AggregateRootId.Equals(streamToAppend.AggregateRootId))
94+
if (AggregateRootId != streamToAppend.AggregateRootId)
9595
{
9696
throw new InvalidOperationException("Cannot append domain events belonging to a different aggregate root.");
9797
}

Src/Xer.DomainDriven/Entity.cs

+29-2
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@ namespace Xer.DomainDriven
44
{
55
public abstract class Entity : IEntity
66
{
7+
#region Properties
8+
79
/// <summary>
810
/// Unique ID.
911
/// </summary>
1012
public Guid Id { get; protected set; }
1113

1214
/// <summary>
13-
/// Date when entitity was created.
15+
/// Date when entitity was created. This will default to <see cref="DateTime.UtcNow"/> if no value has been provided in constructor.
1416
/// </summary>
1517
public DateTime Created { get; protected set; }
1618

1719
/// <summary>
18-
/// Date when entity was last updated.
20+
/// Date when entity was last updated. This will default to <see cref="DateTime.UtcNow"/> if no value has been provided in constructor.
1921
/// </summary>
2022
public DateTime Updated { get; protected set; }
2123

24+
#endregion Properties
25+
26+
#region Constructors
27+
2228
/// <summary>
2329
/// Constructor.
2430
/// </summary>
@@ -45,5 +51,26 @@ public Entity(Guid entityId, DateTime created, DateTime updated)
4551
Created = created;
4652
Updated = updated;
4753
}
54+
55+
#endregion Constructors
56+
57+
#region Methods
58+
59+
/// <summary>
60+
/// Check if entity has the same identity as this entity instance.
61+
/// </summary>
62+
/// <param name="entity">Entity.</param>
63+
/// <returns>True if entities have the same identity. Otherwise, false.</returns>
64+
public virtual bool IsSameAs(IEntity entity)
65+
{
66+
if (entity == null)
67+
{
68+
throw new ArgumentNullException(nameof(entity));
69+
}
70+
71+
return Id == entity.Id;
72+
}
73+
74+
#endregion Methods
4875
}
4976
}

Src/Xer.DomainDriven/Repositories/InMemoryAggregateRootRepository.cs

+1-5
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,7 @@ public InMemoryAggregateRootRepository(bool throwIfAggregateRootIsNotFound)
6969
/// <returns>Asynchronous task.</returns>
7070
public Task SaveAsync(TAggregateRoot aggregateRoot, CancellationToken cancellationToken = default(CancellationToken))
7171
{
72-
if (_aggregateRoots.Contains(aggregateRoot))
73-
{
74-
_aggregateRoots.Remove(aggregateRoot);
75-
}
76-
72+
_aggregateRoots.RemoveAll(a => a.Id == aggregateRoot.Id);
7773
_aggregateRoots.Add(aggregateRoot);
7874

7975
return CompletedTask;

Src/Xer.DomainDriven/Repositories/PublishingRepository.cs Src/Xer.DomainDriven/Repositories/PublishingAggregateRootRepository.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace Xer.DomainDriven.Repositories
66
{
7-
public class PublishingRepository<TAggregateRoot> : IAggregateRootRepository<TAggregateRoot>
8-
where TAggregateRoot : IAggregateRoot
7+
public class PublishingAggregateRootRepository<TAggregateRoot> : IAggregateRootRepository<TAggregateRoot>
8+
where TAggregateRoot : IAggregateRoot
99
{
1010
private readonly IAggregateRootRepository<TAggregateRoot> _inner;
1111
private readonly IDomainEventPublisher _domainEventPublisher;
@@ -15,8 +15,8 @@ public class PublishingRepository<TAggregateRoot> : IAggregateRootRepository<TAg
1515
/// </summary>
1616
/// <param name="inner">Aggregate root repository to decorate.</param>
1717
/// <param name="domainEventPublisher">Domain event publisher.</param>
18-
public PublishingRepository(IAggregateRootRepository<TAggregateRoot> inner,
19-
IDomainEventPublisher domainEventPublisher)
18+
public PublishingAggregateRootRepository(IAggregateRootRepository<TAggregateRoot> inner,
19+
IDomainEventPublisher domainEventPublisher)
2020
{
2121
_inner = inner;
2222
_domainEventPublisher = domainEventPublisher;

Src/Xer.DomainDriven/ValueObject.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public bool Equals(TSelf other)
4343
if (other == null)
4444
return false;
4545

46+
if (ReferenceEquals(this, other))
47+
return true;
48+
49+
if (this.GetType() != other.GetType())
50+
return false;
51+
4652
return ValueEquals(other);
4753
}
4854

@@ -59,7 +65,7 @@ public bool Equals(TSelf other)
5965
return true;
6066
}
6167

62-
if (!ReferenceEquals(obj1, null) && !ReferenceEquals(obj2, null))
68+
if (!ReferenceEquals(obj1, null))
6369
{
6470
return obj1.Equals(obj2);
6571
}

Tests/Xer.DomainDriven.Tests/AggregateRootTests.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using FluentAssertions;
34
using Xer.DomainDriven.Exceptions;
45
using Xer.DomainDriven.Tests.Entities;
@@ -44,7 +45,7 @@ public void ShouldThrowIfNoDomainEventApplierIsRegistered()
4445

4546
#region GetUncommittedDomainEventsMethod
4647

47-
public class GetUncommittedDomainEventsMethod
48+
public class GetDomainEventsMarkedForCommitMethod
4849
{
4950
[Fact]
5051
public void ShouldIncludeAppliedDomainEvent()
@@ -61,9 +62,9 @@ public void ShouldIncludeAppliedDomainEvent()
6162
}
6263
}
6364

64-
#endregion GetUncommittedDomainEventsMethod
65+
#endregion GetDomainEventsMarkedForCommitMethod
6566

66-
#region ClearUncommitedDomainEventsMethod
67+
#region MarkDomainEventsAsCommittedMethod
6768

6869
public class ClearUncommitedDomainEventsMethod
6970
{
@@ -87,6 +88,6 @@ public void ShouldRemoveAllAppliedDomainEvents()
8788
}
8889
}
8990

90-
#endregion ClearUncommitedDomainEventsMethod
91+
#endregion MarkDomainEventsAsCommittedMethod
9192
}
9293
}

Tests/Xer.DomainDriven.Tests/Entities/TestVaueObject.cs

+8
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,12 @@ protected override HashCode GenerateHashCode()
2222
return HashCode.From(Number, Data);
2323
}
2424
}
25+
26+
public class TestValueObjectSecond : TestValueObject
27+
{
28+
public TestValueObjectSecond(string data, int number)
29+
: base(data, number)
30+
{
31+
}
32+
}
2533
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using FluentAssertions;
4+
using Xer.DomainDriven.Repositories;
5+
using Xer.DomainDriven.Tests.Entities;
6+
using Xunit;
7+
8+
namespace Xer.DomainDriven.Tests
9+
{
10+
public class InMemoryAggregateRootRepositoryTests
11+
{
12+
public class SaveAyncMethod
13+
{
14+
[Fact]
15+
public async Task ShouldSaveAggregateRoot()
16+
{
17+
var aggregateRoot = new TestAggregateRoot(Guid.NewGuid());
18+
19+
var repository = new InMemoryAggregateRootRepository<TestAggregateRoot>();
20+
await repository.SaveAsync(aggregateRoot);
21+
22+
var result = await repository.GetByIdAsync(aggregateRoot.Id);
23+
24+
result.Should().Be(aggregateRoot);
25+
}
26+
27+
[Fact]
28+
public async Task ShouldReplaceExistingAggregateRoots()
29+
{
30+
var aggregateRoot1 = new TestAggregateRoot(Guid.NewGuid());
31+
var aggregateRoot2 = new TestAggregateRoot(Guid.NewGuid());
32+
33+
var repository = new InMemoryAggregateRootRepository<TestAggregateRoot>();
34+
await repository.SaveAsync(aggregateRoot1);
35+
await repository.SaveAsync(aggregateRoot2);
36+
37+
var result = await repository.GetByIdAsync(aggregateRoot2.Id);
38+
39+
result.Should().Be(aggregateRoot2);
40+
}
41+
}
42+
}
43+
}

Tests/Xer.DomainDriven.Tests/ValueObjectTests.cs

+96-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using FluentAssertions;
23
using Xer.DomainDriven.Tests.Entities;
34
using Xunit;
@@ -6,10 +7,10 @@ namespace Xer.DomainDriven.Tests
67
{
78
public class ValueObjectTests
89
{
9-
public class EqualsMethod
10+
public class Equality
1011
{
1112
[Fact]
12-
public void ShouldBeTrueIfValueObjectsMatchByValue()
13+
public void EqualityOperatorShouldBeTrueIfValueObjectsMatchByValue()
1314
{
1415
TestValueObject valueObject1 = new TestValueObject("Test", 123);
1516
TestValueObject valueObject2 = new TestValueObject("Test", 123);
@@ -18,7 +19,16 @@ public void ShouldBeTrueIfValueObjectsMatchByValue()
1819
}
1920

2021
[Fact]
21-
public void ShouldNotBeTrueIfValueObjectsDoNotMatchByValue()
22+
public void EqualityOperatorShouldBeTrueIfValueObjectsAreTheSameReference()
23+
{
24+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
25+
TestValueObject sameReference = valueObject1;
26+
27+
(valueObject1 == sameReference).Should().BeTrue();
28+
}
29+
30+
[Fact]
31+
public void EqualityOperatorShouldBeFalseIfValueObjectsDoNotMatchByValue()
2232
{
2333
TestValueObject valueObject1 = new TestValueObject("Test", 123);
2434
TestValueObject valueObject2 = new TestValueObject("Test2", 1234);
@@ -27,13 +37,95 @@ public void ShouldNotBeTrueIfValueObjectsDoNotMatchByValue()
2737
}
2838

2939
[Fact]
30-
public void ShouldNotBeTrueIfComparedWithNull()
40+
public void EqualityOperatorShouldBeFalseIfComparedWithNull()
3141
{
3242
TestValueObject valueObject1 = new TestValueObject("Test", 123);
3343
TestValueObject valueObject2 = null;
3444

3545
(valueObject1 == valueObject2).Should().BeFalse();
3646
}
47+
48+
[Fact]
49+
public void EqualsShouldBeTrueIfValueObjectsMatchByValue()
50+
{
51+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
52+
TestValueObject valueObject2 = new TestValueObject("Test", 123);
53+
54+
valueObject1.Equals(valueObject2).Should().BeTrue();
55+
}
56+
57+
[Fact]
58+
public void EqualsShouldBeTrueIfValueObjectsAreTheSameReference()
59+
{
60+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
61+
TestValueObject sameReference = valueObject1;
62+
63+
valueObject1.Equals(sameReference).Should().BeTrue();
64+
}
65+
66+
[Fact]
67+
public void EqualsShouldNotBeTrueIfValueObjectsDoNotMatchByValue()
68+
{
69+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
70+
TestValueObject valueObject2 = new TestValueObject("Test2", 1234);
71+
72+
valueObject1.Equals(valueObject2).Should().BeFalse();
73+
}
74+
75+
[Fact]
76+
public void EqualsOperatorShouldNotBeTrueIfComparedWithNull()
77+
{
78+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
79+
TestValueObject valueObject2 = null;
80+
81+
valueObject1.Equals(valueObject2).Should().BeFalse();
82+
}
83+
84+
[Fact]
85+
public void ObjectEqualsShouldBeTrueIfValueObjectsMatchByValue()
86+
{
87+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
88+
TestValueObject valueObject2 = new TestValueObject("Test", 123);
89+
90+
valueObject1.Equals((object)valueObject2).Should().BeTrue();
91+
}
92+
93+
[Fact]
94+
public void ObjectEqualsShouldBeTrueIfValueObjectsAreTheSameReference()
95+
{
96+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
97+
TestValueObject sameReference = valueObject1;
98+
99+
valueObject1.Equals((object)sameReference).Should().BeTrue();
100+
}
101+
102+
[Fact]
103+
public void ObjectEqualsShouldNotBeTrueIfValueObjectsDoNotMatchByValue()
104+
{
105+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
106+
TestValueObject valueObject2 = new TestValueObject("Test2", 1234);
107+
108+
valueObject1.Equals((object)valueObject2).Should().BeFalse();
109+
}
110+
111+
[Fact]
112+
public void ObjectEqualsOperatorShouldNotBeTrueIfComparedWithNull()
113+
{
114+
TestValueObject valueObject1 = new TestValueObject("Test", 123);
115+
TestValueObject valueObject2 = null;
116+
117+
valueObject1.Equals((object)valueObject2).Should().BeFalse();
118+
}
119+
120+
[Fact]
121+
public void ShouldNotBeEqualIfValueObjectsMatchByValueButDifferentType()
122+
{
123+
var valueObject1 = new TestValueObject("Test", 123);
124+
var valueObject2 = new TestValueObjectSecond("Test", 123);
125+
126+
// Same value, should be equal.
127+
valueObject1.Should().NotBe(valueObject2);
128+
}
37129
}
38130

39131
public class GetHashCodeMethod

0 commit comments

Comments
 (0)