using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using DotNetCore.CAP.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace DotNetCore.CAP.Test
{
///
/// Allows caller to supply subscribe interface and attribute when adding services.
///
///
///
public class GenericConsumerServiceSelector : ConsumerServiceSelector
where TSubscriptionAttribute : Attribute, INamedGroup
{
private readonly CapOptions _capOptions;
public GenericConsumerServiceSelector(IServiceProvider serviceProvider)
: base(serviceProvider)
{
_capOptions = serviceProvider.GetRequiredService>().Value;
}
///
protected override IEnumerable FindConsumersFromInterfaceTypes(IServiceProvider provider)
{
var executorDescriptorList = new List();
using (var scoped = provider.CreateScope())
{
var scopedProvider = scoped.ServiceProvider;
var subscribers = scopedProvider.GetServices();
var subscriberTypeInfo = typeof(TSubscriber).GetTypeInfo();
foreach (var service in subscribers)
{
var serviceTypeInfo = service?.GetType().GetTypeInfo();
if (serviceTypeInfo == null || !subscriberTypeInfo.IsAssignableFrom(serviceTypeInfo))
{
continue;
}
var descriptors = _GetDescriptors(serviceTypeInfo);
executorDescriptorList.AddRange(descriptors);
}
return executorDescriptorList;
}
}
private IEnumerable _GetDescriptors(TypeInfo typeInfo)
{
foreach (var method in typeInfo.DeclaredMethods)
{
var topicAttr = method.GetCustomAttributes(true);
var topicAttributes = topicAttr as IList ?? topicAttr.ToList();
if (!topicAttributes.Any())
{
continue;
}
foreach (var attr in topicAttributes)
{
_SetAttributeGroup(attr);
yield return new ConsumerExecutorDescriptor
{
Attribute = new CapSubscribeAttribute(attr.Name)
{
Group = attr.Group
},
MethodInfo = method,
ImplTypeInfo = typeInfo,
TopicNamePrefix = _capOptions.TopicNamePrefix,
Parameters = _GetParameterDescriptors(method)
};
}
}
}
private void _SetAttributeGroup(TSubscriptionAttribute attr)
{
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}";
}
}
private IList _GetParameterDescriptors(MethodInfo method)
{
var descriptors = method.GetParameters().Select(p => new ParameterDescriptor()
{Name = p.Name, ParameterType = p.ParameterType, IsFromCap = p.GetCustomAttributes().Any()});
return new List(descriptors.ToArray());
}
}
///
/// Implementers have a name and a group.
///
public interface INamedGroup
{
string Name { get; }
string Group { get; set; }
}
}