Как настроить Масстранзит Потребителей с помощью модулей Autofac - PullRequest
0 голосов
/ 04 ноября 2019

Как зарегистрировать потребителей Masstransit в модулях Autofac.

У меня есть этот код:

 builder.AddMassTransit(configurator =>
        {
            configurator.AddConsumers(ThisAssembly);
            //Bus
            configurator.AddBus(c => c.Resolve<IBusFactory>().CreateBus());
        });

И в другом модуле у меня есть этот код:

public class AutofacModule: Module
{
    public override void Load(ContainerBuilder builder)
    {    
        builder.RegisterConsumers(ThisAssembly);
    }
}

Но Потребители, находящиеся в Модуйском собрании, не найдены Масстранзитом. Пожалуйста, помогите

РЕДАКТИРОВАТЬ: У меня есть несколько сборок (модулей), на которые нет прямой ссылки в стартовом проекте. Сборки загружаются при запуске приложения с использованием MEF из подпапки / Modules. Потребители находятся в этих модулях. Я использую интеграцию Autofac с MEF для загрузки модулей Autofac в конфигурацию Autofac. Когда я говорю, что общественный транспорт не может найти потребителей, я имею в виду следующее: когда я ставлю точку останова, он записывает строку

configurator.AddBus (...)

и осмотрите поле configurator._consumerRegistrations, там нет ни одного, только те из исходного приложения. Также, когда я публикую события, ни один из потребителей, расположенных в этих модулях, не потребляет его. События потребляются только в стартовом приложении.

1 Ответ

2 голосов
/ 05 ноября 2019

После загрузки модулей Autofac и регистрации всех потребителей в контейнере вы можете использовать следующее для регистрации потребителей (и саг):

    public static void AddConsumersFromContainer(this IRegistrationConfigurator configurator, IComponentContext context)
    {
        var consumerTypes = context.FindTypes(IsConsumerOrDefinition);
        configurator.AddConsumers(consumerTypes);
    }

    public static void AddSagasFromContainer(this IRegistrationConfigurator configurator, IComponentContext context)
    {
        var sagaTypes = context.FindTypes(IsSagaOrDefinition);
        configurator.AddSagas(sagaTypes);
    }

    static Type[] FindTypes(this IComponentContext context, Func<Type, bool> filter)
    {
        return context.ComponentRegistry.Registrations
            .SelectMany(r => r.Services.OfType<IServiceWithType>(), (r, s) => (r, s))
            .Where(rs => filter(rs.s.ServiceType))
            .Select(rs => rs.s.ServiceType)
            .ToArray();
    }

    /// <summary>
    /// Returns true if the type is a consumer, or a consumer definition
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsConsumerOrDefinition(Type type)
    {
        Type[] interfaces = type.GetTypeInfo().GetInterfaces();

        return interfaces.Any(t => t.HasInterface(typeof(IConsumer<>)) || t.HasInterface(typeof(IConsumerDefinition<>)));
    }

    /// <summary>
    /// Returns true if the type is a saga, or a saga definition
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsSagaOrDefinition(Type type)
    {
        Type[] interfaces = type.GetTypeInfo().GetInterfaces();

        if (interfaces.Contains(typeof(ISaga)))
            return true;

        return interfaces.Any(t => t.HasInterface(typeof(InitiatedBy<>))
            || t.HasInterface(typeof(Orchestrates<>))
            || t.HasInterface(typeof(Observes<,>))
            || t.HasInterface(typeof(ISagaDefinition<>)));
    }
...