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; } } }