Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read
Q&A

Mapping generic handler to generic query in MediatR

+5
−0

I am using MediatR in an ASP.NET Core 3.1 application and I want use a generic query and a generic request that deals with getting lists of some standard items I am using in drop-downs and similar:

public class GetStandardListItemMapQuery<TEnt> : IRequest<IDictionary<int, StandardListItem>>
    where TEnt : class, IStandardListItem
{
    public GetStandardListItemMapQuery()
    {
        
    }
}

public class GetStandardListItemMapQueryHandler<TEnt> : 
    IRequestHandler<GetStandardListItemMapQuery<TEnt>, IDictionary<int, StandardListItem>>
    where TEnt : class, IStandardListItem
{
    private readonly IApplicationDbContext _context;

    public GetStandardListItemMapQueryHandler(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<IDictionary<int, StandardListItem>> Handle(GetStandardListItemMapQuery<TEnt> request, CancellationToken cancellationToken)
    {
        var dbItems = _context.Set<TEnt>();
        var map = await dbItems
            .Select(e => new {e.Key, e.Value, e.IsEnabled})
            .ToDictionaryAsync(
                e => e.Key, 
                e => new StandardListItem { Key = e.Key, Value = e.Value, IsEnabled = e.IsEnabled }, cancellationToken);
        return map;
    }
}

Registering the mapping between the query and handler like the following works, but it requires explicit call for any used type:

private static void RegisterGenericHandler<TEnt>(IServiceCollection services) where TEnt : class, IStandardListItem
{
    services.AddScoped(typeof(IRequestHandler<GetStandardListItemMapQuery<TEnt>, IDictionary<int, StandardListItem>>),
            typeof(GetStandardListItemMapQueryHandler<TEnt>));
}


private static void RegisterMediatR(IServiceCollection services)
{
    // this does not handle the association for generic queries / handlers
    // (all code is in the same assembly)
    services.AddMediatR(Assembly.GetExecutingAssembly());

    RegisterGenericHandler<Foo>(services);
    RegisterGenericHandler<Bar>(services);
}

I have tried the following, but it does not work as expected:

services.AddScoped(typeof(IRequestHandler<GetStandardListItemMapQuery<IStandardListItem>, IDictionary<int, string>>), 
    typeof(GetStandardListItemMapQueryHandler<IStandardListItem>));

InvalidOperationException: Handler was not found for request of type MediatR.IRequestHandler2 [MyApp.Application.ApplicationUser.Queries.GetReferentials.GetStandardListItemMapQuery1 [MyApp.Domain.Entities.AppUser.Foo],System.Collections.Generic.IDictionary`2 [System.Int32,System.String]]. Register your handlers with the container. See the samples in GitHub for examples.


I have also tried the following binding, but the DI cannot initialize:

services.AddScoped(
    typeof(IRequestHandler<,>)
        .MakeGenericType(typeof(GetStandardListItemMapQuery<>), typeof(IDictionary<int, StandardListItem>)),
    typeof(GetStandardListItemMapQueryHandler<>));

System.ArgumentException: 'Cannot instantiate implementation type 'Ubisoft.MyApp.Application._Playground.GetStandardListItemMapQueryHandler1[TEnt]' for service type 'MediatR.IRequestHandler2[Ubisoft.MyApp.Application._Playground.GetStandardListItemMapQuery1[TEnt],System.Collections.Generic.IDictionary2[System.Int32,Ubisoft.MyApp.Domain.Common.Dtos.StandardListItem]]'.'

Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

0 answers

Sign up to answer this question »

This community is part of the Codidact network. We have other communities too — take a look!

You can also join us in chat!

Want to advertise this community? Use our templates!

Like what we're doing? Support us! Donate