From f879d5b62e3b26d2f43e7f92d1cbfd602514f47f Mon Sep 17 00:00:00 2001 From: Andreas Gehrke Date: Wed, 9 Apr 2025 10:59:16 +0200 Subject: [PATCH 1/3] Ctor on EventStreamId to clone an existing EventStreamId Prevents `string[] parts` allocation, and subsequent `string.Join()` --- src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs b/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs index 827f1d9..9bcbfde 100644 --- a/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs +++ b/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs @@ -16,6 +16,16 @@ public EventStreamId(params string[] parts) Value = string.Join(PartSeperator, parts); } + /// + /// Initializes a new instance of the class from an existing . + /// + /// The existing . + public EventStreamId(EventStreamId existing) + { + Parts = existing.Parts; + Value = existing.Value; + } + public IReadOnlyList Parts { get; } public string Value { get; } From 2facb73bc98f5777318036c5d6687e2a9d17b832 Mon Sep 17 00:00:00 2001 From: Andreas Gehrke Date: Wed, 9 Apr 2025 11:43:48 +0200 Subject: [PATCH 2/3] Add tests of EventStreamId --- .../EventStreamId.cs | 2 +- .../EventStreamIdTests.cs | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/Atc.Cosmos.EventStore.Cqrs.Tests/EventStreamIdTests.cs diff --git a/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs b/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs index 9bcbfde..45a0a44 100644 --- a/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs +++ b/src/Atc.Cosmos.EventStore.Cqrs/EventStreamId.cs @@ -31,7 +31,7 @@ public EventStreamId(EventStreamId existing) public string Value { get; } public static implicit operator EventStreamId(StreamId id) - => FromStreamId(id.Value); + => FromStreamId(id); public static EventStreamId FromStreamId(StreamId id) => new( diff --git a/test/Atc.Cosmos.EventStore.Cqrs.Tests/EventStreamIdTests.cs b/test/Atc.Cosmos.EventStore.Cqrs.Tests/EventStreamIdTests.cs new file mode 100644 index 0000000..94cb010 --- /dev/null +++ b/test/Atc.Cosmos.EventStore.Cqrs.Tests/EventStreamIdTests.cs @@ -0,0 +1,45 @@ +using FluentAssertions; +using Xunit; + +namespace Atc.Cosmos.EventStore.Cqrs.Commands.Tests; + +public class EventStreamIdTests +{ + [Fact] + public void Ctor_must_throw_when_no_arguments_are_provided() + { + Assert.Throws(() => new EventStreamId()); + } + + [Fact] + public void Value_property_must_return_joined_parts() + { + var id = new EventStreamId("foo", "bar"); + id.Value.Should().Be("foo.bar"); + } + + [Fact] + public void Parts_property_must_return_parts() + { + var id = new EventStreamId("foo", "bar"); + id.Parts.Should().BeEquivalentTo("foo", "bar"); + } + + [Fact] + public void EventStreamId_can_be_cloned_using_ctor() + { + var id = new EventStreamId("foo", "bar"); + var clone = new EventStreamId(id); + id.Value.Should().Be(clone.Value); + } + + [Fact] + public void EventStreamId_can_be_created_from_StreamId() + { + var streamId = new StreamId("foo.bar"); + EventStreamId eventStreamId = streamId; + EventStreamId eventStreamId2 = EventStreamId.FromStreamId(streamId); + eventStreamId.Value.Should().Be("foo.bar"); + eventStreamId2.Value.Should().Be("foo.bar"); + } +} \ No newline at end of file From f6979cec7698fe02a5ba113bdb52e503642bc25e Mon Sep 17 00:00:00 2001 From: Andreas Gehrke Date: Wed, 9 Apr 2025 11:51:26 +0200 Subject: [PATCH 3/3] Use TryAdd when registering types in UseCQRS() to prevent duplicate registrations. Similarly to AddEventStore(). --- .../EventStoreOptionsBuilderExtensions.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Atc.Cosmos.EventStore.Cqrs/DependencyInjection/EventStoreOptionsBuilderExtensions.cs b/src/Atc.Cosmos.EventStore.Cqrs/DependencyInjection/EventStoreOptionsBuilderExtensions.cs index a55fc06..01153f8 100644 --- a/src/Atc.Cosmos.EventStore.Cqrs/DependencyInjection/EventStoreOptionsBuilderExtensions.cs +++ b/src/Atc.Cosmos.EventStore.Cqrs/DependencyInjection/EventStoreOptionsBuilderExtensions.cs @@ -18,17 +18,17 @@ public static EventStoreOptionsBuilder UseCQRS( configure?.Invoke(cqrsBuilder); - builder.Services.AddSingleton(typeof(IStateProjector<>), typeof(StateProjector<>)); - builder.Services.AddSingleton(typeof(IStateWriter<>), typeof(StateWriter<>)); - builder.Services.AddTransient(typeof(ICommandProcessor<>), typeof(CommandProcessor<>)); - builder.Services.AddTransient(); - builder.Services.AddTransient(); - builder.Services.AddSingleton(); + builder.Services.TryAddSingleton(typeof(IStateProjector<>), typeof(StateProjector<>)); + builder.Services.TryAddSingleton(typeof(IStateWriter<>), typeof(StateWriter<>)); + builder.Services.TryAddTransient(typeof(ICommandProcessor<>), typeof(CommandProcessor<>)); + builder.Services.TryAddTransient(); + builder.Services.TryAddTransient(); + builder.Services.TryAddSingleton(); - builder.Services.AddSingleton(); + builder.Services.TryAddSingleton(); - builder.Services.AddSingleton(typeof(ProjectionMetadata<>), typeof(ProjectionMetadata<>)); - builder.Services.AddTransient(); + builder.Services.TryAddSingleton(typeof(ProjectionMetadata<>), typeof(ProjectionMetadata<>)); + builder.Services.TryAddTransient(); builder.Services.TryAddSingleton();