Ver a proveniência

Use GenericConsumerServiceSelector in tests. (#843)

Removes sample project.

Co-authored-by: Dave Smith <dave.smith@ventivtech.com>
master
David Smith há 3 anos
committed by GitHub
ascendente
cometimento
9b83982070
Não foi encontrada uma chave conhecida para esta assinatura, na base de dados ID da chave GPG: 4AEE18F83AFDEB23
7 ficheiros alterados com 34 adições e 231 eliminações
  1. +0
    -7
      CAP.sln
  2. +0
    -47
      samples/MyConsumerSelector/CustomSubscriber.cs
  3. +0
    -19
      samples/MyConsumerSelector/MyConsumerSelector.csproj
  4. +0
    -47
      samples/MyConsumerSelector/Program.cs
  5. +0
    -24
      samples/MyConsumerSelector/Selectors.cs
  6. +25
    -83
      test/DotNetCore.CAP.Test/CustomConsumerSubscribeTest.cs
  7. +9
    -4
      test/DotNetCore.CAP.Test/GenericConsumerServiceSelector.cs

+ 0
- 7
CAP.sln Ver ficheiro

@@ -71,8 +71,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCore.CAP.NATS", "src\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.RabbitMQ.Postgres.DashboardAuth", "samples\Sample.RabbitMQ.Postgres.DashboardAuth\Sample.RabbitMQ.Postgres.DashboardAuth.csproj", "{54F6C206-2A23-4971-AE5A-FC47EB772452}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyConsumerSelector", "samples\MyConsumerSelector\MyConsumerSelector.csproj", "{1AE86784-0B64-4A73-8D81-D913C6E33D7D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -167,10 +165,6 @@ Global
{54F6C206-2A23-4971-AE5A-FC47EB772452}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54F6C206-2A23-4971-AE5A-FC47EB772452}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54F6C206-2A23-4971-AE5A-FC47EB772452}.Release|Any CPU.Build.0 = Release|Any CPU
{1AE86784-0B64-4A73-8D81-D913C6E33D7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AE86784-0B64-4A73-8D81-D913C6E33D7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AE86784-0B64-4A73-8D81-D913C6E33D7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AE86784-0B64-4A73-8D81-D913C6E33D7D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -198,7 +192,6 @@ Global
{B187DD15-092D-4B72-9807-50856607D237} = {3A6B6931-A123-477A-9469-8B468B5385AF}
{8B2FD3EA-E72B-4A82-B182-B87EC0C15D07} = {9B2AE124-6636-4DE9-83A3-70360DABD0C4}
{54F6C206-2A23-4971-AE5A-FC47EB772452} = {3A6B6931-A123-477A-9469-8B468B5385AF}
{1AE86784-0B64-4A73-8D81-D913C6E33D7D} = {3A6B6931-A123-477A-9469-8B468B5385AF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2E70565D-94CF-40B4-BFE1-AC18D5F736AB}


+ 0
- 47
samples/MyConsumerSelector/CustomSubscriber.cs Ver ficheiro

@@ -1,47 +0,0 @@
using System;
using DotNetCore.CAP;

namespace MyConsumerSelector
{
public class CustomSubscriber : IMessageSubscriber, ICapSubscribe
{
[MessageSubscription("string")]
public void String(string message)
{
Console.WriteLine($"String: {message}");
}
[MessageSubscription("message.string")]
public void String(Message<string> message)
{
Console.WriteLine($"String: {System.Text.Json.JsonSerializer.Serialize(message)}");
}
[MessageSubscription("message.datetime")]
public void Date(Message<DateTime> message, [FromCap] CapHeader header)
{
Console.WriteLine($"Date: {System.Text.Json.JsonSerializer.Serialize(message)}");
Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(header));
}
[MessageSubscription("message.bytes")]
public void Bytes(Message<byte[]> message, [FromCap] CapHeader header)
{
Console.WriteLine($"Bytes: {System.Text.Json.JsonSerializer.Serialize(message)}");
Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(header));
}

[CapSubscribe("cap")]
public void Cap(string message, [FromCap] CapHeader header)
{
Console.WriteLine($"Cap {message}");
Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(header));
}
}

public class Message<T>
{
public string Name { get; set; }
public T Body { get; set; }
}
}

+ 0
- 19
samples/MyConsumerSelector/MyConsumerSelector.csproj Ver ficheiro

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\DotNetCore.CAP.InMemoryStorage\DotNetCore.CAP.InMemoryStorage.csproj" />
<ProjectReference Include="..\..\src\DotNetCore.CAP.RabbitMQ\DotNetCore.CAP.RabbitMQ.csproj" />
<ProjectReference Include="..\..\src\DotNetCore.CAP\DotNetCore.CAP.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
</ItemGroup>

</Project>

+ 0
- 47
samples/MyConsumerSelector/Program.cs Ver ficheiro

@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using DotNetCore.CAP;
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace MyConsumerSelector
{
public class Program
{
private static bool _useCustomSelector = true;
public static void Main(string[] args)
{
var container = new ServiceCollection();

container.AddLogging(x => x.AddConsole());
if (_useCustomSelector)
container.AddSingleton<IConsumerServiceSelector, GenericConsumerServiceSelector<IMessageSubscriber, MessageSubscriptionAttribute>>();
container.AddTransient<IMessageSubscriber, CustomSubscriber>();
container.AddTransient<ICapSubscribe, CustomSubscriber>();
container.AddCap(x =>
{
x.UseInMemoryStorage();
x.UseRabbitMQ(z =>
{
z.ExchangeName = "MyConsumerSelector.Generic";
z.HostName = "localhost";
z.UserName = "guest";
z.Password = "guest";
z.CustomHeaders = e => new List<KeyValuePair<string, string>>
{
new(DotNetCore.CAP.Messages.Headers.MessageId, SnowflakeId.Default().NextId().ToString()),
new(DotNetCore.CAP.Messages.Headers.MessageName, e.RoutingKey)
};
});
});

var sp = container.BuildServiceProvider();
sp.GetRequiredService<IBootstrapper>().BootstrapAsync(default);
Console.ReadLine();
}
}
}

+ 0
- 24
samples/MyConsumerSelector/Selectors.cs Ver ficheiro

@@ -1,24 +0,0 @@
using System;

namespace MyConsumerSelector
{
/// <summary>
/// Flags the implementer as a class that subscribes to messages.
/// </summary>
public interface IMessageSubscriber { }

/// <summary>
/// Names the message being subscribed to.
/// </summary>
public class MessageSubscriptionAttribute : Attribute, INamedGroup
{
public MessageSubscriptionAttribute(string name)
{
Name = name;
}

public string Name { get; }

public string Group { get; set; }
}
}

+ 25
- 83
test/DotNetCore.CAP.Test/CustomConsumerSubscribeTest.cs Ver ficheiro

@@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;

namespace DotNetCore.CAP.Test
@@ -20,7 +16,8 @@ namespace DotNetCore.CAP.Test
public CustomConsumerSubscribeTest()
{
var services = new ServiceCollection();
services.AddSingleton<IConsumerServiceSelector, MyConsumerServiceSelector>();
// Declare subscribe interface and attribute when configuring services.
services.AddSingleton<IConsumerServiceSelector, GenericConsumerServiceSelector<IMySubscribe, MySubscribeAttribute>>();
services.AddTransient<IMySubscribe, CustomInterfaceTypesClass>();
services.AddLogging();
services.AddCap(x =>
@@ -37,7 +34,7 @@ namespace DotNetCore.CAP.Test
var selector = _provider.GetRequiredService<IConsumerServiceSelector>();
var candidates = selector.SelectCandidates();

Assert.Equal(2, candidates.Count);
Assert.Equal(3, candidates.Count);
}

[Fact]
@@ -53,87 +50,25 @@ namespace DotNetCore.CAP.Test
Assert.StartsWith(TopicNamePrefix, bestCandidates.TopicName);
Assert.Equal(typeof(Task), bestCandidates.MethodInfo.ReturnType);
}
}

public class MyConsumerServiceSelector : ConsumerServiceSelector
{
private readonly CapOptions _capOptions;

public MyConsumerServiceSelector(IServiceProvider serviceProvider)
: base(serviceProvider)
{
_capOptions = serviceProvider.GetService<IOptions<CapOptions>>().Value;
}

protected override IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromInterfaceTypes(IServiceProvider provider)
{
var executorDescriptorList = new List<ConsumerExecutorDescriptor>();

using (var scoped = provider.CreateScope())
{
var scopedProvider = scoped.ServiceProvider;
var consumerServices = scopedProvider.GetServices<IMySubscribe>();
foreach (var service in consumerServices)
{
var typeInfo = service.GetType().GetTypeInfo();
if (!typeof(IMySubscribe).GetTypeInfo().IsAssignableFrom(typeInfo))
{
continue;
}

executorDescriptorList.AddRange(GetMyDescription(typeInfo));
}

return executorDescriptorList;
}
}

private IEnumerable<ConsumerExecutorDescriptor> GetMyDescription(TypeInfo typeInfo)
[Fact]
public void CanFindTopicWithParameters()
{
foreach (var method in typeInfo.DeclaredMethods)
{
var topicAttr = method.GetCustomAttributes<MySubscribeAttribute>(true);
var topicAttributes = topicAttr as IList<MySubscribeAttribute> ?? topicAttr.ToList();

if (!topicAttributes.Any())
{
continue;
}

foreach (var attr in topicAttributes)
{
if (attr.Group == null)
{
attr.Group = _capOptions.DefaultGroupName + "." + _capOptions.Version;
}
else
{
attr.Group = attr.Group + "." + _capOptions.Version;
}

if (!string.IsNullOrEmpty(_capOptions.GroupNamePrefix))
{
attr.Group = $"{_capOptions.GroupNamePrefix}.{attr.Group}";
}
var selector = _provider.GetRequiredService<IConsumerServiceSelector>();
var candidates = selector.SelectCandidates();
var bestCandidates = selector.SelectBestCandidate($"{TopicNamePrefix}.Candidates.Foo3", candidates);

yield return new ConsumerExecutorDescriptor
{
Attribute = new CapSubscribeAttribute(attr.Name)
{
Group = attr.Group
},
MethodInfo = method,
ImplTypeInfo = typeInfo,
TopicNamePrefix = _capOptions.TopicNamePrefix
};
}
}
Assert.NotNull(bestCandidates);
Assert.NotNull(bestCandidates.Parameters);
Assert.StartsWith(GroupNamePrefix, bestCandidates.Attribute.Group);
Assert.StartsWith(TopicNamePrefix, bestCandidates.TopicName);
Assert.Equal(typeof(Task), bestCandidates.MethodInfo.ReturnType);
}
}

public interface IMySubscribe { }

public class MySubscribeAttribute : Attribute
public class MySubscribeAttribute : Attribute, INamedGroup
{
public MySubscribeAttribute(string name)
{
@@ -150,19 +85,26 @@ namespace DotNetCore.CAP.Test
[MySubscribe("Candidates.Foo")]
public Task GetFoo()
{
Console.WriteLine("GetFoo() method has been excuted.");
Console.WriteLine("GetFoo() method has been executed.");
return Task.CompletedTask;
}

[MySubscribe("Candidates.Foo2")]
public void GetFoo2()
{
Console.WriteLine("GetFoo2() method has been excuted.");
Console.WriteLine("GetFoo2() method has been executed.");
}
[MySubscribe("Candidates.Foo3")]
public Task GetFoo3(string message)
{
Console.WriteLine($"GetFoo3() received message {message}.");
return Task.CompletedTask;
}

public void DistracterMethod()
{
Console.WriteLine("DistracterMethod() method has been excuted.");
Console.WriteLine("DistracterMethod() method has been executed.");
}
}
}

samples/MyConsumerSelector/GenericConsumerServiceSelector.cs → test/DotNetCore.CAP.Test/GenericConsumerServiceSelector.cs Ver ficheiro

@@ -2,13 +2,17 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using DotNetCore.CAP;
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace MyConsumerSelector
namespace DotNetCore.CAP.Test
{
/// <summary>
/// Allows caller to supply subscribe interface and attribute when adding services.
/// </summary>
/// <typeparam name="TSubscriber"></typeparam>
/// <typeparam name="TSubscriptionAttribute"></typeparam>
public class GenericConsumerServiceSelector<TSubscriber, TSubscriptionAttribute> : ConsumerServiceSelector
where TSubscriptionAttribute : Attribute, INamedGroup
{
@@ -20,6 +24,7 @@ namespace MyConsumerSelector
_capOptions = serviceProvider.GetRequiredService<IOptions<CapOptions>>().Value;
}

/// <inheritdoc cref="ConsumerServiceSelector"/>
protected override IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromInterfaceTypes(IServiceProvider provider)
{
var executorDescriptorList = new List<ConsumerExecutorDescriptor>();
@@ -31,8 +36,8 @@ namespace MyConsumerSelector
var subscriberTypeInfo = typeof(TSubscriber).GetTypeInfo();
foreach (var service in subscribers)
{
var serviceTypeInfo = service.GetType().GetTypeInfo();
if (!subscriberTypeInfo.IsAssignableFrom(serviceTypeInfo))
var serviceTypeInfo = service?.GetType().GetTypeInfo();
if (serviceTypeInfo == null || !subscriberTypeInfo.IsAssignableFrom(serviceTypeInfo))
{
continue;
}

Carregando…
Cancelar
Guardar