0

I came across Generics open and closed constructed types this question and started toying around with typeof. I am now wondering why I can do this:

var t = typeof(IPipelineBehaviour<,>);

but not this

var s = typeof(IPipelineBehaviour<,List<>>);

Here is a minimal example for use with https://dotnetfiddle.net/

using System;
using System.Collections.Generic;                   

public class Program
{
    public static void Main()
    {
        var t = typeof(IPipelineBehaviour<,>);
        Console.WriteLine(t);
        
        var s = typeof(IPipelineBehaviour<,List<>>);
        Console.WriteLine(s);
    }
}

public interface IPipelineBehaviour<TRequest,TResult>
{

}

I am trying to register an unbound generic for an MediatR.IPipelineBehaviour for which I can assert, that TResult is of type OneOf (see https://github.com/mcintyre321/OneOf ).

I tried to assert it in the class definition through a where clause such as this

public class MyBehaviour<TRequest,TResult> : IPipelineBehaviour<TRequest,TResult>
    where TRequest : IRequest<TResult>
    where TResult : OneOf<???,Problem>
{
    // Implementation goes here
}

but in that case I am lacking the Type indicated as ??? and now I am trying to approach it as follows:

services.AddTransient(typeof(IPipelineBehaviour<,Oneof<,>>), typeof(ValidationBehaviour<,OneOf<,>>);

but it does not work, because typeof(IPipelineBehaviour<,Oneof<,>>) cannot be evaluated.

Benj
  • 889
  • 1
  • 14
  • 31
  • How would `s.MakeGenericType` work in that case? – ProgrammingLlama May 22 '23 at 03:55
  • @ProgrammingLlama I would imagine it goes from left to right through the expression, figure out where types are not provided and then use the method parameters to fill the holes. so `s.MakeGenericType(typeof(object),typeof(object))` would then return `typeof(IPipelineBehaviour>)` – Benj May 22 '23 at 04:09
  • 1
    `IPipelineBehaviour<,>` is a generic type definition, `IPipelineBehaviour<,List<>>` is nothing. You must provide all the generic type parameters. – shingo May 22 '23 at 04:14
  • Why are you lacking the type? If you have no way to decide the type in the definition, don't restrict `TResult` and you will check the type at runtime. – shingo May 22 '23 at 04:20
  • I don't know the type, because there are a plethoria of Query and Command objects that pass through this and the pipline "behaviour" handler is invoked on. I want to implement several of these handlers, ie (if an exception is caught, it is replaced by a `ProblemDetails` , if a validation failed, a `ProblemDetails` is returned). However, for that to work, I need to tell the handler, that TResult is OneOf, otherwise I cannot return it. And it goes against the general idea to implement a handler for each Query/ Command object. – Benj May 22 '23 at 04:24
  • https://github.com/jbogard/MediatR this is the library I am using and this is, how they are usually registered for DI `services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>));` – Benj May 22 '23 at 04:25
  • but if ie the validation fails, then the only option I have, is to throw an exception, which is expensive and disrupts the control flow. I would rather return a ProblemDetails, but for that I need to somehow let the handler know, that both, ProblemDetails and another Result object are valid options to return from there. – Benj May 22 '23 at 04:27
  • 3
    A common misconception is that some people believe that generics are dynamic, but the fact is that generics are static. – shingo May 22 '23 at 05:01
  • _"it goes against the general idea to implement a handler for each Query/ Command object"_ That's the job the `Handle` method needs to do, distribute different types to the corresponding handler. You may expect the service to help you complete this task, but it won't. – shingo May 22 '23 at 05:04
  • So validation, exception catching and all that cross-concern stuff needs to be done in the Handle methods over and over again. What a pity; it would have bee so great to wrap all that into a PipelineBehaviour. Thank you then – Benj May 22 '23 at 05:14

0 Answers0