Skip to content

Commit

Permalink
Add support for singleton entities
Browse files Browse the repository at this point in the history
  • Loading branch information
halgari committed Dec 13, 2023
1 parent ddf0a12 commit 9220312
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 10 deletions.
8 changes: 8 additions & 0 deletions src/NexusMods.EventSourcing.Abstractions/IEntityContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ public interface IEntityContext
public TEntity Get<TEntity>(EntityId<TEntity> id) where TEntity : IEntity;


/// <summary>
/// Gets the singleton entity of the specified type.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public TEntity Get<TEntity>() where TEntity : ISingletonEntity;


/// <summary>
/// Transacts a new event into the context.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace NexusMods.EventSourcing.Abstractions;
/// <summary>
/// Marks this entity as a singleton entity, the singleton id is used to retrieve the entity from the cache.
/// </summary>
public interface ISingletonEntity
public interface ISingletonEntity : IEntity
{
public static virtual EntityId SingletonId { get; }
}
5 changes: 5 additions & 0 deletions src/NexusMods.EventSourcing/EntityContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ public TEntity Get<TEntity>(EntityId<TEntity> id) where TEntity : IEntity
throw new System.NotImplementedException();
}

public TEntity Get<TEntity>() where TEntity : ISingletonEntity
{
throw new System.NotImplementedException();
}

public ValueTask Add<TEvent>(TEvent entity) where TEvent : IEvent
{
throw new System.NotImplementedException();
Expand Down
2 changes: 1 addition & 1 deletion src/NexusMods.EventSourcing/EventFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace NexusMods.EventSourcing;

public class EventFormatter : MemoryPackFormatter<IEvent>
internal class EventFormatter : MemoryPackFormatter<IEvent>
{
private static Guid _zeroGuid = Guid.Empty;
private readonly Dictionary<Guid,Type> _eventByGuid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public async ValueTask Apply<T>(T context) where T : IEventContext
{
context.New(Id);
context.Emit(Id, Loadout._name, Name);
context.Emit(LoadoutRegistry.SingletonId, LoadoutRegistry._loadouts, Id);
}

public static CreateLoadout Create(string name) => new() { Name = name, Id = EntityId<Loadout>.NewId() };
Expand Down
10 changes: 2 additions & 8 deletions tests/NexusMods.EventSourcing.TestModel/Model/LoadoutRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@

namespace NexusMods.EventSourcing.TestModel.Model;

public class LoadoutRegistry(IEntityContext context, EntityId id) : AEntity(context, id)
public class LoadoutRegistry(IEntityContext context) : AEntity(context, SingletonId.Value), ISingletonEntity
{
/// <summary>
/// Gets the instance of the loadout registry from the entity context.
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static LoadoutRegistry GetInstance(IEntityContext context) =>
context.Get(EntityId<LoadoutRegistry>.From("10BAE6BA-D5F9-40F4-AF7F-CCA1417C3BB0"));
public static EntityId<LoadoutRegistry> SingletonId => EntityId<LoadoutRegistry>.From("10BAE6BA-D5F9-40F4-AF7F-CCA1417C3BB0");

/// <summary>
/// The loadouts in the registry.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NexusMods.EventSourcing.TestModel.Events;
using NexusMods.EventSourcing.TestModel.Model;
using NexusMods.EventSourcing.Tests.Contexts;

namespace NexusMods.EventSourcing.Tests;
Expand Down Expand Up @@ -73,4 +74,11 @@ public async void CanDeleteEntities()

loadout.Mods.First().Name.Should().Be("Second Mod");
}

[Fact]
public async void CanGetSingletonEntities()
{
var entity = _ctx.Get<LoadoutRegistry>();
entity.Should().NotBeNull();
}
}
13 changes: 13 additions & 0 deletions tests/NexusMods.EventSourcing.Tests/Contexts/TestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ public TEntity Get<TEntity>(EntityId<TEntity> id) where TEntity : IEntity
return createdEntity;
}

public TEntity Get<TEntity>() where TEntity : ISingletonEntity
{
var id = TEntity.SingletonId;
if (_entities.TryGetValue(id, out var entity))
{
return (TEntity)entity;
}

var instance = (TEntity)Activator.CreateInstance(typeof(TEntity), this)!;
_entities.Add(id, instance);
return instance;
}

private Dictionary<IAttribute, IAccumulator> LoadValues(EntityId id)
{
var ingester = new Ingester(id);
Expand Down

0 comments on commit 9220312

Please sign in to comment.