* change the IConsumerServiceSelector interface access modifier * change the IConsumerServiceSelector interface access modifiermaster
@@ -68,6 +68,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCore.CAP.InMemoryStor | |||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.AzureServiceBus.InMemory", "samples\Sample.AzureServiceBus.InMemory\Sample.AzureServiceBus.InMemory.csproj", "{1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.AzureServiceBus.InMemory", "samples\Sample.AzureServiceBus.InMemory\Sample.AzureServiceBus.InMemory.csproj", "{1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}" | ||||
EndProject | EndProject | ||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetCore.CAP.CastleCoreTest", "test\DotNetCore.CAP.CastleCoreTest\DotNetCore.CAP.CastleCoreTest.csproj", "{BA499B87-77A9-43A2-98A3-89ECF5034E26}" | |||||
EndProject | |||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|Any CPU = Debug|Any CPU | Debug|Any CPU = Debug|Any CPU | ||||
@@ -142,6 +144,10 @@ Global | |||||
{1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU | {1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU | {1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
{1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}.Release|Any CPU.Build.0 = Release|Any CPU | {1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
{BA499B87-77A9-43A2-98A3-89ECF5034E26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{BA499B87-77A9-43A2-98A3-89ECF5034E26}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{BA499B87-77A9-43A2-98A3-89ECF5034E26}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{BA499B87-77A9-43A2-98A3-89ECF5034E26}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
@@ -165,6 +171,7 @@ Global | |||||
{63B2A464-FBEA-42FB-8EFA-98AFA39FC920} = {9B2AE124-6636-4DE9-83A3-70360DABD0C4} | {63B2A464-FBEA-42FB-8EFA-98AFA39FC920} = {9B2AE124-6636-4DE9-83A3-70360DABD0C4} | ||||
{58B6E829-C6C8-457C-9DD0-C600650254DF} = {9B2AE124-6636-4DE9-83A3-70360DABD0C4} | {58B6E829-C6C8-457C-9DD0-C600650254DF} = {9B2AE124-6636-4DE9-83A3-70360DABD0C4} | ||||
{1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8} = {3A6B6931-A123-477A-9469-8B468B5385AF} | {1E1E959C-3D0E-45C3-ABCA-DAAACE68AAB8} = {3A6B6931-A123-477A-9469-8B468B5385AF} | ||||
{BA499B87-77A9-43A2-98A3-89ECF5034E26} = {C09CDAB0-6DD4-46E9-B7F3-3EF2A4741EA0} | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(ExtensibilityGlobals) = postSolution | GlobalSection(ExtensibilityGlobals) = postSolution | ||||
SolutionGuid = {2E70565D-94CF-40B4-BFE1-AC18D5F736AB} | SolutionGuid = {2E70565D-94CF-40B4-BFE1-AC18D5F736AB} | ||||
@@ -4,7 +4,7 @@ | |||||
using System.Reflection; | using System.Reflection; | ||||
using DotNetCore.CAP.Abstractions; | using DotNetCore.CAP.Abstractions; | ||||
namespace DotNetCore.CAP.Internal | |||||
namespace DotNetCore.CAP | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// A descriptor of user definition method. | /// A descriptor of user definition method. |
@@ -11,13 +11,13 @@ using DotNetCore.CAP.Infrastructure; | |||||
using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
namespace DotNetCore.CAP.Internal | |||||
namespace DotNetCore.CAP | |||||
{ | { | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
/// <summary> | /// <summary> | ||||
/// A default <see cref="T:DotNetCore.CAP.Abstractions.IConsumerServiceSelector" /> implementation. | /// A default <see cref="T:DotNetCore.CAP.Abstractions.IConsumerServiceSelector" /> implementation. | ||||
/// </summary> | /// </summary> | ||||
internal class DefaultConsumerServiceSelector : IConsumerServiceSelector | |||||
public class DefaultConsumerServiceSelector : IConsumerServiceSelector | |||||
{ | { | ||||
private readonly CapOptions _capOptions; | private readonly CapOptions _capOptions; | ||||
private readonly IServiceProvider _serviceProvider; | private readonly IServiceProvider _serviceProvider; | ||||
@@ -71,7 +71,7 @@ namespace DotNetCore.CAP.Internal | |||||
return result; | return result; | ||||
} | } | ||||
private IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromInterfaceTypes( | |||||
protected virtual IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromInterfaceTypes( | |||||
IServiceProvider provider) | IServiceProvider provider) | ||||
{ | { | ||||
var executorDescriptorList = new List<ConsumerExecutorDescriptor>(); | var executorDescriptorList = new List<ConsumerExecutorDescriptor>(); | ||||
@@ -95,7 +95,7 @@ namespace DotNetCore.CAP.Internal | |||||
} | } | ||||
} | } | ||||
private IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromControllerTypes() | |||||
protected virtual IEnumerable<ConsumerExecutorDescriptor> FindConsumersFromControllerTypes() | |||||
{ | { | ||||
var executorDescriptorList = new List<ConsumerExecutorDescriptor>(); | var executorDescriptorList = new List<ConsumerExecutorDescriptor>(); | ||||
@@ -112,7 +112,7 @@ namespace DotNetCore.CAP.Internal | |||||
return executorDescriptorList; | return executorDescriptorList; | ||||
} | } | ||||
private IEnumerable<ConsumerExecutorDescriptor> GetTopicAttributesDescription(TypeInfo typeInfo) | |||||
protected IEnumerable<ConsumerExecutorDescriptor> GetTopicAttributesDescription(TypeInfo typeInfo) | |||||
{ | { | ||||
foreach (var method in typeInfo.DeclaredMethods) | foreach (var method in typeInfo.DeclaredMethods) | ||||
{ | { |
@@ -3,12 +3,12 @@ | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
namespace DotNetCore.CAP.Internal | |||||
namespace DotNetCore.CAP | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Defines an interface for selecting an consumer service method to invoke for the current message. | /// Defines an interface for selecting an consumer service method to invoke for the current message. | ||||
/// </summary> | /// </summary> | ||||
internal interface IConsumerServiceSelector | |||||
public interface IConsumerServiceSelector | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// Selects a set of <see cref="ConsumerExecutorDescriptor" /> candidates for the current message associated with | /// Selects a set of <see cref="ConsumerExecutorDescriptor" /> candidates for the current message associated with |
@@ -0,0 +1,58 @@ | |||||
using Castle.DynamicProxy; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||||
using System; | |||||
using Xunit; | |||||
namespace DotNetCore.CAP.CastleDynamicProxyTest | |||||
{ | |||||
public class ConsumerServiceSelectorTest | |||||
{ | |||||
private IServiceProvider _provider; | |||||
public ConsumerServiceSelectorTest() | |||||
{ | |||||
var services = new ServiceCollection(); | |||||
services.AddSingleton(typeof(ICapSubscribe), f => | |||||
{ | |||||
var generator = new ProxyGenerator(); | |||||
return generator.CreateClassProxy(typeof(TestSubscribeClass)); | |||||
}); | |||||
services.AddSingleton<ITestSubscribeClass, TestSubscribeClass>(); | |||||
services.AddLogging(); | |||||
services.TryAddSingleton<IConsumerServiceSelector, CastleCoreConsumerServiceSelector>(); | |||||
services.AddCap(x => { }); | |||||
_provider = services.BuildServiceProvider(); | |||||
} | |||||
[Theory] | |||||
[InlineData("cap.castle.sub")] | |||||
public void CanFindCapSubscribeTopic(string topic) | |||||
{ | |||||
var selector = _provider.GetRequiredService<IConsumerServiceSelector>(); | |||||
var candidates = selector.SelectCandidates(); | |||||
Assert.Equal(2, candidates.Count); | |||||
} | |||||
} | |||||
public interface ITestSubscribeClass | |||||
{ | |||||
} | |||||
public class TestSubscribeClass : ITestSubscribeClass, ICapSubscribe | |||||
{ | |||||
[CapSubscribe("cap.castle.sub")] | |||||
public void TestSubscribe(DateTime dateTime) | |||||
{ | |||||
Console.WriteLine(dateTime); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,22 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | |||||
<PropertyGroup> | |||||
<TargetFramework>netcoreapp2.2</TargetFramework> | |||||
<IsPackable>false</IsPackable> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Castle.Core" Version="4.4.0" /> | |||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> | |||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" /> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | |||||
<PackageReference Include="xunit" Version="2.4.0" /> | |||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\..\src\DotNetCore.CAP\DotNetCore.CAP.csproj" /> | |||||
</ItemGroup> | |||||
</Project> |
@@ -0,0 +1,46 @@ | |||||
using Castle.Core; | |||||
using Castle.DynamicProxy; | |||||
using DotNetCore.CAP.Infrastructure; | |||||
using Microsoft.Extensions.DependencyInjection; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Reflection; | |||||
namespace DotNetCore.CAP.CastleDynamicProxyTest | |||||
{ | |||||
public class CastleCoreConsumerServiceSelector : DefaultConsumerServiceSelector | |||||
{ | |||||
public CastleCoreConsumerServiceSelector(IServiceProvider serviceProvider, CapOptions capOptions) | |||||
: base(serviceProvider, capOptions) | |||||
{ | |||||
} | |||||
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<ICapSubscribe>(); | |||||
foreach (var service in consumerServices) | |||||
{ | |||||
var serviceType = service.GetType(); | |||||
// Castle dynamic proxy... | |||||
TypeInfo typeInfo = ProxyServices.IsDynamicProxy(serviceType) ? ProxyUtil.GetUnproxiedType(service).GetTypeInfo() | |||||
: serviceType.GetTypeInfo(); | |||||
if (!typeof(ICapSubscribe).GetTypeInfo().IsAssignableFrom(typeInfo)) | |||||
{ | |||||
continue; | |||||
} | |||||
executorDescriptorList.AddRange(GetTopicAttributesDescription(typeInfo)); | |||||
} | |||||
return executorDescriptorList; | |||||
} | |||||
} | |||||
} | |||||
} |