diff --git a/src/Samples/Sample.Serialization.ConsoleApp/Program.cs b/src/Samples/Sample.Serialization.ConsoleApp/Program.cs
index 15a7face..c775e5c0 100644
--- a/src/Samples/Sample.Serialization.ConsoleApp/Program.cs
+++ b/src/Samples/Sample.Serialization.ConsoleApp/Program.cs
@@ -11,7 +11,6 @@
using SlimMessageBus.Host;
using SlimMessageBus.Host.Memory;
using SlimMessageBus.Host.Redis;
-using SlimMessageBus.Host.Serialization;
using SlimMessageBus.Host.Serialization.Avro;
using SlimMessageBus.Host.Serialization.Hybrid;
using SlimMessageBus.Host.Serialization.Json;
@@ -27,7 +26,7 @@ enum Provider
///
/// This sample shows:
-/// 1. How tu use the Avro serializer (for contract Avro IDL first apprach to generate C# code)
+/// 1. How tu use the Avro serializer (for contract Avro IDL first approach to generate C# code)
/// 2. How to combine two serializer approaches in one app (using the Hybrid serializer).
///
class Program
@@ -40,17 +39,11 @@ static async Task Main(string[] args) => await Host.CreateDefaultBuilder(args)
services.AddHostedService();
- // alternatively a simpler approach, but using the slower ReflectionMessageCreationStategy and ReflectionSchemaLookupStrategy
- var avroSerializer = new AvroMessageSerializer();
-
- // Avro serialized using the AvroConvert library - no schema generation neeeded upfront.
- var jsonSerializer = new JsonMessageSerializer();
-
services
.AddSlimMessageBus(mbb =>
{
// Note: remember that Memory provider does not support req-resp yet.
- var provider = Provider.Redis;
+ var provider = Provider.Memory;
/*
var sl = new DictionarySchemaLookupStrategy();
@@ -59,7 +52,7 @@ static async Task Main(string[] args) => await Host.CreateDefaultBuilder(args)
sl.Add(typeof(MultiplyRequest), MultiplyRequest._SCHEMA);
sl.Add(typeof(MultiplyResponse), MultiplyResponse._SCHEMA);
- var mf = new DictionaryMessageCreationStategy();
+ var mf = new DictionaryMessageCreationStrategy();
/// register all your types
mf.Add(typeof(AddCommand), () => new AddCommand());
mf.Add(typeof(MultiplyRequest), () => new MultiplyRequest());
@@ -72,12 +65,14 @@ static async Task Main(string[] args) => await Host.CreateDefaultBuilder(args)
mbb
.AddServicesFromAssemblyContaining()
// Note: Certain messages will be serialized by one Avro serializer, other using the Json serializer
- .AddHybridSerializer(new Dictionary
+ .AddAvroSerializer()
+ .AddJsonSerializer()
+ // Include AddHybridSerializer after other serializers so that the DI container can be updated
+ .AddHybridSerializer(o =>
{
- [jsonSerializer] = new[] { typeof(SubtractCommand) }, // the first one will be the default serializer, no need to declare types here
- [avroSerializer] = new[] { typeof(AddCommand), typeof(MultiplyRequest), typeof(MultiplyResponse) },
- }, defaultMessageSerializer: jsonSerializer)
-
+ //o.Add(typeof(SubtractCommand)); // can also be omitted as JsonMessageSerializer is the default
+ o.Add(typeof(AddCommand), typeof(MultiplyRequest), typeof(MultiplyResponse));
+ })
.Produce(x => x.DefaultTopic("AddCommand"))
.Consume(x => x.Topic("AddCommand").WithConsumer())
@@ -221,7 +216,7 @@ public class SubtractCommandConsumer : IConsumer
{
public async Task OnHandle(SubtractCommand message)
{
- Console.WriteLine("Consumer: Subracting {0} and {1} gives {2}", message.Left, message.Right, message.Left - message.Right);
+ Console.WriteLine("Consumer: Subtracting {0} and {1} gives {2}", message.Left, message.Right, message.Left - message.Right);
await Task.Delay(50); // Simulate some work
}
}
diff --git a/src/SlimMessageBus.Host.Serialization.Avro/AvroMessageSerializer.cs b/src/SlimMessageBus.Host.Serialization.Avro/AvroMessageSerializer.cs
index 831796af..38a3a5a5 100644
--- a/src/SlimMessageBus.Host.Serialization.Avro/AvroMessageSerializer.cs
+++ b/src/SlimMessageBus.Host.Serialization.Avro/AvroMessageSerializer.cs
@@ -84,7 +84,7 @@ public object Deserialize(Type t, byte[] payload)
var writerSchema = WriteSchemaLookup(t);
AssertSchemaNotNull(t, writerSchema, true);
- _logger.LogDebug("Type {0} writer schema: {1}, reader schema: {2}", t, writerSchema, readerSchema);
+ _logger.LogDebug("Type {MessageType} writer schema: {WriterSchema}, reader schema: {ReaderSchema}", t, writerSchema, readerSchema);
var reader = new SpecificDefaultReader(writerSchema, readerSchema);
reader.Read(message, dec);
@@ -108,7 +108,7 @@ public byte[] Serialize(Type t, object message)
var writerSchema = WriteSchemaLookup(t);
AssertSchemaNotNull(t, writerSchema, true);
- _logger.LogDebug("Type {0} writer schema: {1}", t, writerSchema);
+ _logger.LogDebug("Type {MessageType} writer schema: {WriterSchema}", t, writerSchema);
var writer = new SpecificDefaultWriter(writerSchema); // Schema comes from pre-compiled, code-gen phase
writer.Write(message, enc);
diff --git a/src/SlimMessageBus.Host.Serialization.Hybrid/HybridMessageSerializer.cs b/src/SlimMessageBus.Host.Serialization.Hybrid/HybridMessageSerializer.cs
index 5d2106f7..2645a345 100644
--- a/src/SlimMessageBus.Host.Serialization.Hybrid/HybridMessageSerializer.cs
+++ b/src/SlimMessageBus.Host.Serialization.Hybrid/HybridMessageSerializer.cs
@@ -8,10 +8,12 @@
public class HybridMessageSerializer : IMessageSerializer
{
private readonly ILogger _logger;
- private readonly IList _serializers = new List();
- private readonly IDictionary _serializerByType = new Dictionary();
+ private readonly Dictionary _serializerByType = [];
+
public IMessageSerializer DefaultSerializer { get; set; }
+ internal IReadOnlyDictionary SerializerByType => _serializerByType;
+
public HybridMessageSerializer(ILogger logger, IDictionary registration, IMessageSerializer defaultMessageSerializer = null)
{
_logger = logger;
@@ -24,12 +26,14 @@ public HybridMessageSerializer(ILogger logger, IDiction
public void Add(IMessageSerializer serializer, params Type[] supportedTypes)
{
- if (_serializers.Count == 0 && DefaultSerializer == null)
- {
- DefaultSerializer = serializer;
- }
+#if NETSTANDARD2_0
+ if (serializer is null) throw new ArgumentNullException(nameof(serializer));
+#else
+ ArgumentNullException.ThrowIfNull(serializer);
+#endif
+
+ DefaultSerializer ??= serializer;
- _serializers.Add(serializer);
foreach (var type in supportedTypes)
{
_serializerByType.Add(type, serializer);
@@ -38,19 +42,19 @@ public void Add(IMessageSerializer serializer, params Type[] supportedTypes)
protected virtual IMessageSerializer MatchSerializer(Type t)
{
- if (_serializers.Count == 0)
- {
- throw new InvalidOperationException("No serializers registered.");
- }
-
if (!_serializerByType.TryGetValue(t, out var serializer))
{
- // use first as default
- _logger.LogTrace("Serializer for type {0} not registered, will use default serializer", t);
+ _logger.LogTrace("Serializer for type {MessageType} not registered, will use default serializer", t);
+
+ if (DefaultSerializer == null)
+ {
+ throw new InvalidOperationException("No serializers registered.");
+ }
+
serializer = DefaultSerializer;
}
- _logger.LogDebug("Serializer for type {0} will be {1}", t, serializer);
+ _logger.LogDebug("Serializer for type {MessageType} will be {Serializer}", t, serializer);
return serializer;
}
diff --git a/src/SlimMessageBus.Host.Serialization.Hybrid/MessageBusBuilderExtensions.cs b/src/SlimMessageBus.Host.Serialization.Hybrid/MessageBusBuilderExtensions.cs
index b2a82cb6..5e04f2fe 100644
--- a/src/SlimMessageBus.Host.Serialization.Hybrid/MessageBusBuilderExtensions.cs
+++ b/src/SlimMessageBus.Host.Serialization.Hybrid/MessageBusBuilderExtensions.cs
@@ -1,5 +1,7 @@
namespace SlimMessageBus.Host.Serialization.Hybrid;
+using System.Collections.Concurrent;
+
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
@@ -24,4 +26,50 @@ public static MessageBusBuilder AddHybridSerializer(this MessageBusBuilder mbb,
});
return mbb;
}
+
+ ///
+ /// Registers the with implementation as using serializers as registered in the .
+ ///
+ ///
+ /// Action to register serializers for dependency injection resolution.
+ /// The default serializer to be used when the message type cannot be matched
+ ///
+ public static MessageBusBuilder AddHybridSerializer(this MessageBusBuilder mbb, Action registration)
+ where TDefaultSerializer : class, IMessageSerializer
+ {
+ mbb.PostConfigurationActions.Add(services =>
+ {
+ services.RemoveAll(typeof(IMessageSerializer));
+ services.TryAddSingleton(svp =>
+ {
+ var builder = new HybridSerializerOptionsBuilder();
+ registration(builder);
+
+ var registrations = builder.Registrations.ToDictionary(x => (IMessageSerializer)svp.GetRequiredService(x.Key), x => x.Value.ToArray());
+ var defaultMessageSerializer = svp.GetRequiredService();
+ return new HybridMessageSerializer(svp.GetRequiredService>(), registrations, defaultMessageSerializer);
+ });
+
+ services.TryAddSingleton(svp => svp.GetRequiredService());
+ });
+ return mbb;
+ }
+
+ public sealed class HybridSerializerOptionsBuilder
+ {
+ internal ConcurrentDictionary> Registrations { get; } = new();
+
+ public HybridSerializerOptionsBuilder Add(params Type[] types)
+ where TMessageSerializer : IMessageSerializer
+ {
+ if (types.Length == 0)
+ {
+ return this;
+ }
+
+ Registrations.GetOrAdd(typeof(TMessageSerializer), _ => []).AddRange(types);
+
+ return this;
+ }
+ }
}
diff --git a/src/SlimMessageBus.Host.Serialization.Hybrid/README.md b/src/SlimMessageBus.Host.Serialization.Hybrid/README.md
index b1da2153..fc26cbcf 100644
--- a/src/SlimMessageBus.Host.Serialization.Hybrid/README.md
+++ b/src/SlimMessageBus.Host.Serialization.Hybrid/README.md
@@ -1,4 +1,30 @@
# What
-Message serialization that based on message type delegates to the respective serializer.
+Message serialization that is based on message type, delegating serialization to the respective serializer.
+```c#
+
+ services
+ .AddSlimMessageBus(mbb =>
+ {
+ mbb
+ // add required serializers to the DI container first
+ .AddAvroSerializer()
+ .AddGoogleProtobufSerializer()
+ .AddJsonSerializer()
+
+ // Add hybrid serializer last so that it can update DI container and set itself as the default
+ .AddHybridSerializer(
+ o => {
+
+ // Message1, Message2 => AvroSerializer
+ // Message3 => GoogleProtobufMessageSerializer
+ // all other messages by JsonMessageSerializer
+
+ o.Add(typeof(Message1), typeof(Message2));
+ o.Add(typeof(Message3));
+ })
+ ...
+ }
+
+```
diff --git a/src/SlimMessageBus.Host.Serialization.Hybrid/SlimMessageBus.Host.Serialization.Hybrid.csproj b/src/SlimMessageBus.Host.Serialization.Hybrid/SlimMessageBus.Host.Serialization.Hybrid.csproj
index f6633595..eb09035e 100644
--- a/src/SlimMessageBus.Host.Serialization.Hybrid/SlimMessageBus.Host.Serialization.Hybrid.csproj
+++ b/src/SlimMessageBus.Host.Serialization.Hybrid/SlimMessageBus.Host.Serialization.Hybrid.csproj
@@ -16,4 +16,8 @@
+
+
+
+
diff --git a/src/SlimMessageBus.sln b/src/SlimMessageBus.sln
index 885de7c5..ae9bdd87 100644
--- a/src/SlimMessageBus.sln
+++ b/src/SlimMessageBus.sln
@@ -230,9 +230,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlimMessageBus.Host.RabbitM
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlimMessageBus.Host.RabbitMQ.Test", "Tests\SlimMessageBus.Host.RabbitMQ.Test\SlimMessageBus.Host.RabbitMQ.Test.csproj", "{F5373E1D-A2B4-46CC-9B07-94F6655C8E29}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlimMessageBus.Host.Sql", "SlimMessageBus.Host.Sql\SlimMessageBus.Host.Sql.csproj", "{5EED0E89-2475-40E0-81EF-0F05C9326612}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlimMessageBus.Host.Sql", "SlimMessageBus.Host.Sql\SlimMessageBus.Host.Sql.csproj", "{5EED0E89-2475-40E0-81EF-0F05C9326612}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlimMessageBus.Host.Sql.Common", "SlimMessageBus.Host.Sql.Common\SlimMessageBus.Host.Sql.Common.csproj", "{F19B7A21-7749-465A-8810-4C274A9E8956}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlimMessageBus.Host.Sql.Common", "SlimMessageBus.Host.Sql.Common\SlimMessageBus.Host.Sql.Common.csproj", "{F19B7A21-7749-465A-8810-4C274A9E8956}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlimMessageBus.Host.Serialization.Hybrid.Test", "Tests\SlimMessageBus.Host.Serialization.Hybrid.Test\SlimMessageBus.Host.Serialization.Hybrid.Test.csproj", "{DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -730,6 +732,14 @@ Global
{F19B7A21-7749-465A-8810-4C274A9E8956}.Release|Any CPU.Build.0 = Release|Any CPU
{F19B7A21-7749-465A-8810-4C274A9E8956}.Release|x86.ActiveCfg = Release|Any CPU
{F19B7A21-7749-465A-8810-4C274A9E8956}.Release|x86.Build.0 = Release|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Debug|x86.Build.0 = Debug|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Release|x86.ActiveCfg = Release|Any CPU
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -803,6 +813,7 @@ Global
{F5373E1D-A2B4-46CC-9B07-94F6655C8E29} = {9F005B5C-A856-4351-8C0C-47A8B785C637}
{5EED0E89-2475-40E0-81EF-0F05C9326612} = {9291D340-B4FA-44A3-8060-C14743FB1712}
{F19B7A21-7749-465A-8810-4C274A9E8956} = {9291D340-B4FA-44A3-8060-C14743FB1712}
+ {DB624D5F-CB7C-4E16-B1E2-3B368FCB5A46} = {9F005B5C-A856-4351-8C0C-47A8B785C637}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {435A0D65-610C-4B84-B1AA-2C7FBE72DB80}
diff --git a/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/Helpers/SampleMessages.cs b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/Helpers/SampleMessages.cs
new file mode 100644
index 00000000..7ebf5623
--- /dev/null
+++ b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/Helpers/SampleMessages.cs
@@ -0,0 +1,6 @@
+namespace SlimMessageBus.Host.Serialization.Hybrid.Test.Helpers
+{
+ public record SampleOne;
+ public record SampleTwo;
+ public record SampleThree;
+}
diff --git a/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/HybridMessageSerializerTests.cs b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/HybridMessageSerializerTests.cs
new file mode 100644
index 00000000..45576ce0
--- /dev/null
+++ b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/HybridMessageSerializerTests.cs
@@ -0,0 +1,112 @@
+namespace SlimMessageBus.Host.Serialization.Hybrid.Test
+{
+ using System;
+
+ using FluentAssertions;
+
+ using Microsoft.Extensions.Logging;
+
+ using Moq;
+
+ using SlimMessageBus.Host.Serialization.Hybrid.Test.Helpers;
+
+ public class HybridMessageSerializerTests
+ {
+ [Fact]
+ public void When_ConstructorReceivesARepeatedDefinition_Then_ThrowException()
+ {
+ // arrange
+ var mockDefaultSerializer = new Mock();
+ var mockSerializer1 = new Mock();
+ var mockSerializer2 = new Mock();
+ var mockLogger = new Mock>();
+
+ var serializers = new Dictionary
+ {
+ { mockSerializer1.Object, new[] { typeof(SampleOne), typeof(SampleTwo) } },
+ { mockSerializer2.Object, new[] { typeof(SampleOne) } },
+ };
+
+ // act
+ var act = () => new HybridMessageSerializer(mockLogger.Object, serializers, mockDefaultSerializer.Object);
+
+ // assert
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public void When_NoDefaultSerializerIsSupplied_Then_UseFirstSpecialist()
+ {
+ // arrange
+ var mockDefaultSerializer = new Mock();
+ var mockSerializer1 = new Mock();
+ var mockLogger = new Mock>();
+
+ var serializers = new Dictionary
+ {
+ { mockDefaultSerializer.Object, new[] { typeof(SampleOne) } },
+ { mockSerializer1.Object, new[] { typeof(SampleTwo) } },
+ };
+
+ // act
+ var target = new HybridMessageSerializer(mockLogger.Object, serializers, default);
+ var actual = target.DefaultSerializer;
+
+ // assert
+ actual.Should().BeEquivalentTo(mockDefaultSerializer.Object);
+ }
+
+ [Fact]
+ public void When_ASpecialisedMessageIsSerialized_Then_UseSpecializedSerializer()
+ {
+ // arrange
+ var mockDefaultSerializer = new Mock();
+
+ var mockSerializer1 = new Mock();
+ mockSerializer1.Setup(x => x.Serialize(typeof(SampleOne), It.IsAny())).Verifiable(Times.Once());
+
+ var mockSerializer2 = new Mock();
+
+ var mockLogger = new Mock>();
+ var serializers = new Dictionary
+ {
+ { mockSerializer1.Object, new[] { typeof(SampleOne) } },
+ { mockSerializer2.Object, new[] { typeof(SampleTwo) } },
+ };
+
+ // act
+ var target = new HybridMessageSerializer(mockLogger.Object, serializers, mockDefaultSerializer.Object);
+ var _ = target.Serialize(typeof(SampleOne), new SampleOne());
+
+ // assert
+ mockSerializer1.Verify(x => x.Serialize(typeof(SampleOne), It.IsAny()));
+ mockSerializer2.VerifyNoOtherCalls();
+ mockDefaultSerializer.VerifyNoOtherCalls();
+ }
+
+ [Fact]
+ public void When_AGenericMessageIsSerialized_Then_UseDefaultSerializer()
+ {
+ // arrange
+ var mockDefaultSerializer = new Mock();
+ mockDefaultSerializer.Setup(x => x.Serialize(typeof(SampleOne), It.IsAny())).Verifiable(Times.Once());
+
+ var mockSerializer1 = new Mock();
+
+ var mockLogger = new Mock>();
+ var serializers = new Dictionary
+ {
+ { mockSerializer1.Object, new[] { typeof(SampleTwo) } }
+ };
+
+ // act
+ var target = new HybridMessageSerializer(mockLogger.Object, serializers, mockDefaultSerializer.Object);
+ var _ = target.Serialize(typeof(SampleOne), new SampleOne());
+
+ // assert
+ mockDefaultSerializer.Verify(x => x.Serialize(typeof(SampleOne), It.IsAny()));
+ mockSerializer1.VerifyNoOtherCalls();
+ }
+ }
+}
+
diff --git a/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/MessageBusBuilderExtensionsTests.cs b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/MessageBusBuilderExtensionsTests.cs
new file mode 100644
index 00000000..ff3d35dd
--- /dev/null
+++ b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/MessageBusBuilderExtensionsTests.cs
@@ -0,0 +1,94 @@
+namespace SlimMessageBus.Host.Serialization.Hybrid.Test;
+
+using System;
+
+using FluentAssertions;
+
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Logging;
+
+using Moq;
+
+using SlimMessageBus.Host.Serialization.Hybrid;
+using SlimMessageBus.Host.Serialization.Hybrid.Test.Helpers;
+
+public class MessageBusBuilderExtensionsTests
+{
+ private readonly IServiceCollection _services;
+
+ public MessageBusBuilderExtensionsTests()
+ {
+ // arrange
+ var mockLogger = new Mock>();
+
+ _services = new ServiceCollection();
+ _services.AddSingleton(mockLogger.Object);
+ _services.TryAddSingleton(svp => new SerializerOne());
+ _services.TryAddSingleton(svp => svp.GetRequiredService());
+ _services.TryAddSingleton(svp => new SerializerTwo());
+ _services.TryAddSingleton(svp => svp.GetRequiredService());
+ _services.TryAddSingleton(svp => new SerializerThree());
+ _services.TryAddSingleton(svp => svp.GetRequiredService());
+
+ // act
+ _services.AddSlimMessageBus(cfg =>
+ {
+ cfg.AddHybridSerializer(o =>
+ {
+ o.Add(typeof(SampleTwo));
+ o.Add(typeof(SampleThree));
+ });
+ });
+ }
+
+ [Fact]
+ public void When_IMessageSerializerRegistrationsAlreadyExist_Then_RemovePreviousRegistrations()
+ {
+ // assert
+ _services.Count(x => x.ServiceType == typeof(IMessageSerializer)).Should().Be(1);
+ }
+
+ [Fact]
+ public void When_HybridMessageSerializerIsAdded_Then_RegisterAsIMessageSerializer()
+ {
+ // act
+ var serviceProvider = _services.BuildServiceProvider();
+ var target = serviceProvider.GetServices().ToList();
+
+ // assert
+ target.Count.Should().Be(1);
+ target.Single().GetType().Should().Be(typeof(HybridMessageSerializer));
+ }
+
+ [Fact]
+ public void When_HybridMessageSerializerIsAdded_Then_SerializersAndTypesShouldConfigured()
+ {
+ // act
+ var serviceProvider = _services.BuildServiceProvider();
+ var target = serviceProvider.GetService();
+
+ // assert
+ target.DefaultSerializer.GetType().Should().Be(typeof(SerializerOne));
+ target.SerializerByType.Count.Should().Be(2);
+ target.SerializerByType.Should().ContainKey(typeof(SampleTwo)).WhoseValue.Should().BeOfType();
+ target.SerializerByType.Should().ContainKey(typeof(SampleThree)).WhoseValue.Should().BeOfType();
+ }
+
+ public abstract class AbstractSerializer : IMessageSerializer
+ {
+ public object Deserialize(Type t, byte[] payload)
+ {
+ throw new NotImplementedException();
+ }
+
+ public byte[] Serialize(Type t, object message)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class SerializerOne : AbstractSerializer { }
+ public class SerializerTwo : AbstractSerializer { }
+ public class SerializerThree : AbstractSerializer { }
+}
\ No newline at end of file
diff --git a/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/SlimMessageBus.Host.Serialization.Hybrid.Test.csproj b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/SlimMessageBus.Host.Serialization.Hybrid.Test.csproj
new file mode 100644
index 00000000..5006b25a
--- /dev/null
+++ b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/SlimMessageBus.Host.Serialization.Hybrid.Test.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/Usings.cs b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/Usings.cs
new file mode 100644
index 00000000..8c927eb7
--- /dev/null
+++ b/src/Tests/SlimMessageBus.Host.Serialization.Hybrid.Test/Usings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file