Notifications
Sign Up Sign In
Q&A

Mapping generic handler to generic query in MediatR

+2
−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 [PtbNext.Application.ApplicationUser.Queries.GetReferentials.GetStandardListItemMapQuery1 [PtbNext.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.

Why should this post be closed?

0 comments

0 answers

Sign up to answer this question »