Выполнение препроцессора MediatR только для определенных типов интерфейсов (команд)C#

Место общения программистов C#
Ответить
Anonymous
 Выполнение препроцессора MediatR только для определенных типов интерфейсов (команд)

Сообщение Anonymous »

[ПРИМЕЧАНИЕ: Это вопрос «замены». Первый был основан на коде моего основного проекта, поэтому я переделал вопрос, используя код из одноцелевого проекта, который более четко иллюстрирует принцип. Вопрос остается тем же, только лучше сформулирован.]
Сценарий
Я пытаюсь настроить препроцессор команд в конвейере запросов CQRS, используя поведение конвейера MediatR и Autofac для маршрутизации запросов. Моя цель состоит в том, чтобы препроцессор запускался только для команд (ICommand), а не для всех запросов (IRequest), что приведет к выполнению препроцессором команд, запросов и событий.
Проблема
Я могу заставить свой GenericPreProcessor или любой другой препроцессор нормально работать для всех типов запросов, но любой метод, который я использовал, чтобы попытаться «фильтровать» внедрение либо возвращает ошибку, либо просто не выполняет нужный препроцессор.
Моя конфигурация конвейера «работа для всех запросов» в Autofac выглядит следующим образом:

Код: Выделить всё

// Pipeline pre/post processors
builder
.RegisterGeneric(typeof(RequestPostProcessorBehavior))
.As(typeof(IPipelineBehavior));

builder
.RegisterGeneric(typeof(RequestPreProcessorBehavior))
.As(typeof(IPipelineBehavior));

// Works as desired: Fires generic pre-processor for ALL requests, both cmd and query
builder
.RegisterGeneric(typeof(GenericRequestPreProcessor))
.As(typeof(IRequestPreProcessor));

// Works for all requests, but I need a way to limit it to commands
builder
.RegisterGeneric(typeof(MyCommandPreProcessor))
.As(typeof(IRequestPreProcessor));
Концептуально я пытаюсь сделать что-то вроде любого из этих, но безуспешно:

Код: Выделить всё

builder
.RegisterGeneric(typeof(MyCommandPreProcessor)) // Note generic
.As(typeof(IRequestPreProcessor));
// Intellisense error "Unexpected use of an unbound generic"

builder
.RegisterType(typeof(MyCommandPreProcessor)) // Note non-generic
.As(typeof(IRequestPreProcessor));
// Intellisense error "Unexpected use of an unbound generic"

builder
.RegisterType(typeof(MyCommandPreProcessor)) // Note non-generic
.As(typeof(IRequestPreProcessor));
// No errors, but MyCommandPreProcessor not firing
Я пробую несколько разных конфигураций для MyCommandPreProcessor, универсальную и неуниверсальную, но одна из них меня озадачила:

Код: Выделить всё

public class MyCommandPreProcessor  : IRequestPreProcessor
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}

- OR -

public class MyCommandPreProcessor : IRequestPreProcessor
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}
Мой вопрос
Есть идеи о том, как зарегистрировать препроцессор, который будет работать только с типами IRequest, которые являются закрытыми типами ICommand?
Вспомогательные материалы
Проект на GitHub
Весь минимальный пример проекта можно просмотреть или клонирован по адресу https://github.com/jhoiby/MediatRPreProcessorTest
Autofac MediatR Config
Рабочая конфигурация с одним GenericRequestPreProcessor для всех запросов.

Код: Выделить всё

        builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();

var mediatrOpenTypes = new[]
{
typeof(IRequestHandler),
typeof(IRequestHandler),
typeof(INotificationHandler)
};

foreach (var mediatrOpenType in mediatrOpenTypes)
{
// Register all command handler in the same assembly as WriteLogMessageCommandHandler
builder
.RegisterAssemblyTypes(typeof(MyCommandHandler).GetTypeInfo().Assembly)
.AsClosedTypesOf(mediatrOpenType)
.AsImplementedInterfaces();

// Register all QueryHandlers in the same assembly as GetExternalLoginQueryHandler
builder
.RegisterAssemblyTypes(typeof(MyQueryHandler).GetTypeInfo().Assembly)
.AsClosedTypesOf(mediatrOpenType)
.AsImplementedInterfaces();
}

// Pipeline pre/post processors
builder.RegisterGeneric(typeof(RequestPostProcessorBehavior)).As(typeof(IPipelineBehavior));
builder.RegisterGeneric(typeof(RequestPreProcessorBehavior)).As(typeof(IPipelineBehavior));
builder.RegisterGeneric(typeof(GenericRequestPreProcessor)).As(typeof(IRequestPreProcessor));
// builder.RegisterGeneric(typeof(GenericRequestPostProcessor)).As(typeof(IRequestPostProcessor));
// builder.RegisterGeneric(typeof(GenericPipelineBehavior)).As(typeof(IPipelineBehavior));

builder.Register(ctx =>
{
var c = ctx.Resolve();
return t => c.Resolve(t);
});

builder.Register(ctx =>
{
var c = ctx.Resolve();
return t => (IEnumerable)c.Resolve(typeof(IEnumerable).MakeGenericType(t));
});
Класс MyCommandPreProcessor
Я экспериментирую с обоими из них, универсальными и неуниверсальными:

Код: Выделить всё

public class MyCommandPreProcessor : IRequestPreProcessor
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}

- AND -

public class MyCommandPreProcessor : IRequestPreProcessor
{
public Task Process(TRequest request, CancellationToken cancellationToken)
{
Debug.WriteLine("***** MYCOMMAND PREPROCESSOR CALLED *****");
return Task.CompletedTask;
}
}
Структуры наследования

Код: Выделить всё

// Requests

IMediatR.IRequest


Подробнее здесь: [url]https://stackoverflow.com/questions/48045989/executing-mediatr-preprocessor-only-for-specific-interface-types-commands[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»