using System; using System.Collections.Generic; using Elsa.Activities.MassTransit.Activities; using Elsa.Activities.MassTransit.Consumers; using Elsa.Activities.MassTransit.Options; using Elsa.Core.Extensions; using MassTransit; using MassTransit.AspNetCoreIntegration; using MassTransit.AspNetCoreIntegration.HealthChecks; using MassTransit.ExtensionsDependencyInjectionIntegration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; namespace Elsa.Activities.MassTransit.Extensions { public static class ServiceCollectionExtensions { public static IServiceCollection AddRabbitMqActivities(this IServiceCollection services, Action> options = null, params Type[] messageTypes) { var optionsBuilder = services.AddOptions(); options?.Invoke(optionsBuilder); services .AddActivity() .AddActivity(); services.AddSingleton(); services.AddSingleton(); services.AddMassTransit( massTransit => { massTransit.AddBus(sp => CreateUsingRabbitMq(massTransit, sp, messageTypes)); }); services.AddSingleton(); foreach (var messageType in messageTypes) { var consumerType = CreateConsumerType(messageType); services.AddSingleton(consumerType); } return services; } private static IBusControl CreateUsingRabbitMq(IServiceCollectionConfigurator massTransit, IServiceProvider sp, IEnumerable messageTypes) { return Bus.Factory.CreateUsingRabbitMq( bus => { var options = sp.GetRequiredService>(); var host = bus.Host(new Uri(options.Value.Host), _ => { }); foreach (var messageType in messageTypes) { var queueName = messageType.Name; var consumerType = CreateConsumerType(messageType); bus.ReceiveEndpoint( host, queueName, endpoint => { endpoint.PrefetchCount = 16; endpoint.Consumer(consumerType, sp.GetRequiredService); MapEndpointConvention(messageType, endpoint.InputAddress); }); } }); } private static void MapEndpointConvention(Type messageType, Uri destinationAddress) { var method = typeof(EndpointConvention).GetMethod("Map", new[]{ typeof(Uri) }); var generic = method.MakeGenericMethod(messageType); generic.Invoke(null, new object[]{destinationAddress}); } private static Type CreateConsumerType(Type messageType) { return typeof(WorkflowConsumer<>).MakeGenericType(messageType); } } }