Ausführen des MediatR-Präprozessors nur für bestimmte Schnittstellentypen (Befehle)C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Ausführen des MediatR-Präprozessors nur für bestimmte Schnittstellentypen (Befehle)

Post by Anonymous »

[HINWEIS: Dies ist eine „Ersatz“-Frage. Die erste basierte auf dem Code meines Hauptprojekts, daher habe ich die Frage mit Code aus einem Einzweckprojekt überarbeitet, der das Prinzip klarer veranschaulicht. Die Frage bleibt dieselbe, nur besser dargestellt.]
Das Szenario
Ich versuche, einen Befehlsvorprozessor auf einer CQRS-Anfragepipeline einzurichten, indem ich das Verhalten der MediatR-Pipeline und Autofac für die Anfrageweiterleitung verwende. Mein Ziel ist es, dass der Präprozessor nur für Befehle (ICommand) und nicht für alle Anfragen (IRequest) ausgeführt wird, was dazu führt, dass der Präprozessor für Befehle, Abfragen und Ereignisse ausgeführt wird.
Das Problem
Ich kann meinen GenericPreProcessor oder einen anderen Präprozessor für alle Arten von Anfragen einwandfrei laufen lassen, aber auch für jede Methode, mit der ich versucht habe, die Injektion zu „filtern“. gibt einen Fehler zurück oder führt den gewünschten Vorprozessor einfach nicht aus.
Meine Pipeline-Konfiguration für alle Anforderungen in Autofac sieht folgendermaßen aus:

Code: Select all

// 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));
Konzeptionell versuche ich, so etwas zu machen, was scheitert:

Code: Select all

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
Ich probiere ein paar verschiedene Konfigurationen für MyCommandPreProcessor aus, eine generische und eine nicht-generische, bin aber bei keiner davon ratlos:

Code: Select all

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;
}
}
Meine Frage https://github.com/jhoiby/MediatRPreProcessorTest
Autofac MediatR-Konfiguration
Eine funktionierende Konfiguration mit einem einzigen GenericRequestPreProcessor für alle Anfragen.

Code: Select all

        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-Klasse
Ich experimentiere mit beiden, generischen und nicht generischen:

Code: Select all

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

Code: Select all

// Requests

IMediatR.IRequest

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post