Skip to content

Commit

Permalink
Make Entity implement IComparable
Browse files Browse the repository at this point in the history
Having Entity implement IComparable allows entities to be
implicitly used as equality components in ValueObjects.
  • Loading branch information
robertlarkins committed Jun 28, 2023
1 parent d2e833c commit a6bdde5
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
72 changes: 72 additions & 0 deletions CSharpFunctionalExtensions.Tests/EntityTests/IComparableTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Linq;
using FluentAssertions;
using Xunit;

namespace CSharpFunctionalExtensions.Tests.EntityTests
{
public class IComparableTests
{
[Fact]
public void Can_sort_entities()
{
var entity1 = new MyEntity(1);
var entity2 = new MyEntity(2);
var entity3 = new MyEntity(3);
var entity4 = new MyEntity(4);

MyEntity[] myEntities = new[] { entity3, entity1, entity4, entity2 }
.OrderBy(x => x)
.ToArray();

myEntities[0].Should().BeSameAs(entity1);
myEntities[1].Should().BeSameAs(entity2);
myEntities[2].Should().BeSameAs(entity3);
myEntities[3].Should().BeSameAs(entity4);
}

[Fact]
public void Entities_with_different_id_types_are_comparatively_null()
{
var longEntity = new MyEntity(1);
var guidEntity = new MyOtherEntity(new Guid("282e6fe9-a272-45da-aa16-757449ab2818"));

int result1 = longEntity.CompareTo(guidEntity);
int result2 = guidEntity.CompareTo(longEntity);

result1.Should().Be(1);
result2.Should().Be(1);
}

[Fact]
public void Can_sort_entity_that_is_null()
{
var entity1 = new MyEntity(1);
var entity2 = new MyEntity(2);

MyEntity[] entities = new[] { entity1, entity2, null }
.OrderBy(x => x)
.ToArray();

entities[0].Should().BeNull();
entities[1].Should().BeSameAs(entity1);
entities[2].Should().BeSameAs(entity2);
}

private class MyEntity : Entity
{
public MyEntity(long id)
: base(id)
{
}
}

private class MyOtherEntity : Entity<Guid>
{
public MyOtherEntity(Guid id)
: base(id)
{
}
}
}
}
22 changes: 20 additions & 2 deletions CSharpFunctionalExtensions/Entity/Entity.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace CSharpFunctionalExtensions
using System;

namespace CSharpFunctionalExtensions
{
public abstract class Entity<TId>
public abstract class Entity<TId> : IComparable, IComparable<Entity<TId>> where TId : IComparable<TId>
{
public virtual TId Id { get; protected set; }

Expand Down Expand Up @@ -55,6 +57,22 @@ public override int GetHashCode()
{
return (ValueObject.GetUnproxiedType(this).ToString() + Id).GetHashCode();
}

public virtual int CompareTo(Entity<TId> other)
{
if (other is null)
return 1;

if (ReferenceEquals(this, other))
return 0;

return Id.CompareTo(other.Id);
}

public virtual int CompareTo(object other)
{
return CompareTo(other as Entity<TId>);
}
}

public abstract class Entity : Entity<long>
Expand Down
4 changes: 2 additions & 2 deletions CSharpFunctionalExtensions/ValueObject/ValueObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public virtual int CompareTo(ValueObject other)
return
GetEqualityComponents().Zip(
other.GetEqualityComponents(),
(left, rigth) =>
left?.CompareTo(rigth) ?? (rigth is null ? 0 : -1))
(left, right) =>
left?.CompareTo(right) ?? (right is null ? 0 : -1))
.FirstOrDefault(cmp => cmp != 0);
}

Expand Down

0 comments on commit a6bdde5

Please sign in to comment.