Merge pull request 'Added translators feature' (#8) from Translators into main
Reviewed-on: #8
This commit is contained in:
commit
7bfdd64d25
8
src.sln
8
src.sln
|
@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProSol.Messaging", "src\fixMessaging.csproj", "{89203112-653F-4A81-A3B9-9B711E5F6A6B}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProSol.Messaging", "src\Messaging.csproj", "{89203112-653F-4A81-A3B9-9B711E5F6A6B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Messaging.Tests", "tests\Messaging.Tests.csproj", "{9D9B8827-380D-4AE5-8BA5-F4056935C13A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -18,5 +20,9 @@ Global
|
|||
{89203112-653F-4A81-A3B9-9B711E5F6A6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{89203112-653F-4A81-A3B9-9B711E5F6A6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{89203112-653F-4A81-A3B9-9B711E5F6A6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9D9B8827-380D-4AE5-8BA5-F4056935C13A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9D9B8827-380D-4AE5-8BA5-F4056935C13A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9D9B8827-380D-4AE5-8BA5-F4056935C13A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9D9B8827-380D-4AE5-8BA5-F4056935C13A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -10,5 +10,5 @@ public interface IPublisher<TMessage>
|
|||
/// </summary>
|
||||
/// <param name="subscriber"> Target. </param>
|
||||
/// <returns> Custom IDisposable implementation. </returns>
|
||||
Unsubscriber<TMessage> Subscribe(ISubscriber<TMessage> subscriber);
|
||||
}
|
||||
IDisposable Subscribe(ISubscriber<TMessage> subscriber);
|
||||
}
|
||||
|
|
|
@ -7,4 +7,9 @@
|
|||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
|
||||
<_Parameter1>$(AssemblyName).Tests</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
namespace ProSol.Messaging;
|
||||
using ProSol.Messaging.Translating;
|
||||
|
||||
namespace ProSol.Messaging;
|
||||
|
||||
/// <summary>
|
||||
/// Collects a subscribers and publishes a messages to them.
|
||||
/// Provides a pipeline mechanics, so a subscriber is able to stop message processing.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMessage"> Type of message. </typeparam>
|
||||
public class PipelinePublisher<TMessage> : IPublisher<TMessage>
|
||||
public class PipelineMessagePublisher<TMessage> :
|
||||
IPublisher<TMessage>,
|
||||
ITranslatorPublisher<TMessage>
|
||||
{
|
||||
private readonly HashSet<ISubscriber<TMessage>> subscribers = [];
|
||||
|
||||
|
@ -14,12 +18,20 @@ public class PipelinePublisher<TMessage> : IPublisher<TMessage>
|
|||
/// </summary>
|
||||
/// <param name="subscriber"> An implementation of <see cref="ISubscriber"/> or <see cref="SubscriptionBase"/> interfaces. </param>
|
||||
/// <returns> Unsubscriber. </returns>
|
||||
public Unsubscriber<TMessage> Subscribe(ISubscriber<TMessage> subscriber)
|
||||
public IDisposable Subscribe(ISubscriber<TMessage> subscriber)
|
||||
{
|
||||
subscribers.Add(subscriber);
|
||||
return new Unsubscriber<TMessage>(subscribers, subscriber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes a subscriber in different message format.
|
||||
/// </summary>
|
||||
public IDisposable Subscribe<TDest>(TranslatorBase<TMessage, TDest> translator)
|
||||
{
|
||||
return Subscribe(translator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes the message to subscribers.
|
||||
/// </summary>
|
||||
|
@ -49,7 +61,7 @@ public class PipelinePublisher<TMessage> : IPublisher<TMessage>
|
|||
return;
|
||||
}
|
||||
|
||||
NextDelegate next = () => PublishInternal(subscribers.Skip(1), message);
|
||||
void next() => PublishInternal(subscribers.Skip(1), message);
|
||||
subscribers.First().OnNext(message, next);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace ProSol.Messaging.Translating;
|
||||
|
||||
public interface ITranslatorPublisher<TMessage>
|
||||
{
|
||||
IDisposable Subscribe<TDest>(TranslatorBase<TMessage, TDest> translatorBase);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace ProSol.Messaging.Translating;
|
||||
|
||||
internal sealed class SimpleTranslator<TSource, TDest>(ISubscriber<TDest> destSubscriber, Func<TSource, TDest> converter)
|
||||
: TranslatorBase<TSource, TDest>(destSubscriber)
|
||||
{
|
||||
protected override TDest ConvertMessage(TSource message)
|
||||
=> converter(message);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
namespace ProSol.Messaging.Translating;
|
||||
|
||||
public abstract class TranslatorBase<TSource, TDest>(ISubscriber<TDest> destSubscriber) : ISubscriber<TSource>
|
||||
{
|
||||
private readonly ISubscriber<TDest> destSubscriber = destSubscriber;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCompleted() => destSubscriber.OnCompleted();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNext(TSource message, NextDelegate next) => destSubscriber.OnNext(ConvertMessage(message), next);
|
||||
|
||||
protected abstract TDest ConvertMessage(TSource message);
|
||||
|
||||
public static TranslatorBase<TSource, TDest> Create(ISubscriber<TDest> destSubscriber, Func<TSource, TDest> converter)
|
||||
=> new SimpleTranslator<TSource, TDest>(destSubscriber, converter);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
global using NUnit.Framework;
|
|
@ -0,0 +1,35 @@
|
|||
using FakeItEasy;
|
||||
using ProSol.Messaging;
|
||||
using ProSol.Messaging.Translating;
|
||||
|
||||
namespace Messaging.Tests;
|
||||
|
||||
public class MessageTranslatorTests
|
||||
{
|
||||
[Test]
|
||||
public void SimpleCase_OneToOne_ShouldWork()
|
||||
{
|
||||
// Arrange configs.
|
||||
string[] input = ["Hello", "World!"];
|
||||
int[] expected = [5, 6];
|
||||
static int converter(string message) => message.Length;
|
||||
List<int> messages = [];
|
||||
|
||||
// Arrange operations.
|
||||
var fakeListener = A.Fake<ISubscriber<int>>();
|
||||
A.CallTo(() => fakeListener.OnNext(A<int>._, A<NextDelegate>._))
|
||||
.Invokes((int i, NextDelegate next) => messages.Add(i));
|
||||
|
||||
var publisher = new PipelineMessagePublisher<string>();
|
||||
publisher.Subscribe(TranslatorBase<string, int>.Create(fakeListener, converter));
|
||||
|
||||
// Act.
|
||||
foreach(var item in input)
|
||||
{
|
||||
publisher.Publish(item);
|
||||
}
|
||||
|
||||
// Assert.
|
||||
Assert.That(messages, Is.EquivalentTo(expected));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FakeItEasy" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\src\Messaging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue