Skip to content
This repository was archived by the owner on Feb 15, 2023. It is now read-only.

Add behaviors registration for certain request types #75

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

xneg
Copy link

@xneg xneg commented Aug 14, 2019

Hi!

When I use MediatR I miss one important feature. I want to register Behaviors not only for certain Request and Response or for generic TRequest and TResponse. But I also want behaviors that triggers on some generic request. I think the best way to explain what I want is to show the code:

public interface ICommon { }

public class MyRequest1 : ICommon, IRequest<string> { }

public class MyRequest2 : ICommon, IRequest<int> { }

public class MyRequest3 : IRequest<int> { }

So I want to register some behavior that triggers only on requests that implement ICommon:

public class InterfaceBehavior<T> : IPipelineBehavior<ICommon, T>
{
    public async Task<T> Handle(ICommon request, CancellationToken cancellationToken, RequestHandlerDelegate<T> next)
    {
        return await next();
    }
}

With standard Microsoft.DependecyInjection I could not do such a thing. So I wrote an extension method that sort through all request that implement ICommon and register behavior for them. It looks like:

services.AddBehaviorsForRequest<ICommon>(typeof(Startup));

Maybe my implementation is naive and does not take into account corner cases but I think it is better than nothing.

If you accept my idea I can add tests for this functional.

@pastushenkoy
Copy link

That's what I need as well. Looking forward to get this feature.

@jbogard
Copy link
Owner

jbogard commented Aug 19, 2019

Hrmmmm....I think the problem is that I'd still want to do a generic constraint instead of a partially closed type.

@xneg
Copy link
Author

xneg commented Aug 19, 2019

The problem with generic constraint is that it is a constraint. Even in your example

public class ConstrainedBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
            where TRequest : Ping
            where TResponse : Pong

if you send through MediatR any request that does not satisfy constraint it will throw exception.

@lilasquared
Copy link

@xneg can't you just constrain the request?

public class ConstrainedBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
            where TRequest : ICommon<TResponse>

@xneg
Copy link
Author

xneg commented Aug 19, 2019

@lilasquared then my request that does not implement ICommon<TResponse> e.g. MyRequest3 will fail.

@jbogard
Copy link
Owner

jbogard commented Aug 19, 2019

@lilasquared so the problem with that is ASP.NET Core DI does not support constrained generics. The only way to solve it is to not register constrained open generics, but instead to register only the closed types.

@jbogard
Copy link
Owner

jbogard commented Aug 19, 2019

Which I'm open for btw - if the only way we can get around constrained generics is to try and close the types, that's what we'd have to do.

One problem is that I don't scan for request types at the moment, only handler types. If you gave me handlers in assembly B that refers to request types in assembly A, right now I don't know about assembly A.

@xneg
Copy link
Author

xneg commented Aug 19, 2019

I think the responsibility for checking and adding assemblies to scan lies with those who will use this method. But I admit it can be not 100% robust in some corner cases.

@pastushenkoy
Copy link

Which I'm open for btw - if the only way we can get around constrained generics is to try and close the types, that's what we'd have to do.

One problem is that I don't scan for request types at the moment, only handler types. If you gave me handlers in assembly B that refers to request types in assembly A, right now I don't know about assembly A.

We can make it work through handlers: find handlers in the given assembly and take requests from them. Will it suit you?

@jbogard
Copy link
Owner

jbogard commented Aug 19, 2019 via email

@pastushenkoy
Copy link

We rewrote registrar. @jbogard , please take a look.

@xneg
Copy link
Author

xneg commented Aug 25, 2019

@jbogard so what do you think?

@pastushenkoy
Copy link

@jbogard please give us some feedback. copying this thing from one project to another is pretty annoying.

@jbogard
Copy link
Owner

jbogard commented Feb 18, 2020

Looks good - I realized I don't have an editorconfig in the root. Let me add one so that the style matches (tabs).

@xneg
Copy link
Author

xneg commented Feb 20, 2020

Hi! I added .editorconfig and refomated code according to it.

@xneg
Copy link
Author

xneg commented Feb 27, 2020

@jbogard

@jbogard
Copy link
Owner

jbogard commented Jan 6, 2022

I think this can be closed as the .NET Core DI supports constrained generics as of 5.0

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants