You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向MediatR传递实体?泛型查询处理类容器注册报错问题咨询

Fixing MediatR Generic Base Class Registration & Entity Passing Issues

Let's break down your problems and walk through the solutions step by step:

1. Resolving the "Register your handlers with the container" Error

The root cause here is that your generic handler is nested inside a generic query class, and MediatR's automatic assembly scanning might not pick up this nested open-generic type correctly. By default, MediatR looks for non-generic handlers or explicitly defined generic implementations, but nested open-generics need a little extra configuration.

Fix: Register the Open-Generic Handler Explicitly

Update your DI registration (usually in Program.cs or Startup.cs) to explicitly register the generic handler type:

builder.Services.AddMediatR(cfg =>
{
    // First, scan the assembly where your base query/handler lives
    cfg.RegisterServicesFromAssembly(typeof(GetAllBaseQuery<>).Assembly);
    
    // Explicitly register the open-generic handler to cover all T types
    cfg.AddOpenGenericHandler(typeof(GetAllBaseQuery<>.GetAllBaseQueryHandler<>));
});

Alternatively, you can register it directly via the DI container's open-generic support:

builder.Services.AddScoped(
    typeof(IRequestHandler<GetAllBaseQuery<T>, IResponseDTO>), 
    typeof(GetAllBaseQuery<T>.GetAllBaseQueryHandler<T>)
);

This tells the DI container how to resolve the handler for any T that meets the class constraint.

2. Improving the Generic Query/Handler Design

Your current base class returns a non-generic IResponseDTO, which can lead to type-safety issues. Let's make it more robust by using a generic response type:

// First, define a generic response interface for type safety
public interface IResponseDTO<T> : IResponseDTO
{
    IEnumerable<T> Data { get; set; }
    bool IsSuccess { get; set; }
    string Message { get; set; }
}

// Implement the generic response (adjust based on your existing DTO structure)
public class ResponseDTO<T> : IResponseDTO<T>
{
    public IEnumerable<T> Data { get; set; } = Enumerable.Empty<T>();
    public bool IsSuccess { get; set; } = true;
    public string Message { get; set; } = string.Empty;
}

// Update your base query to use the generic response
public class GetAllBaseQuery<T> : IRequest<IResponseDTO<T>> where T : class 
{
    // Add properties here if you need to pass query parameters (e.g., pagination, filters)
    public int PageNumber { get; set; } = 1;
    public int PageSize { get; set; } = 10;

    // Keep the handler nested, but update it to return the generic response
    public class GetAllBaseQueryHandler : IRequestHandler<GetAllBaseQuery<T>, IResponseDTO<T>> 
    {
        private readonly IBaseResponse _repo;

        public GetAllBaseQueryHandler(IBaseResponse repo) 
        {
            _repo = repo;
        }

        public async Task<IResponseDTO<T>> Handle(GetAllBaseQuery<T> query, CancellationToken cancellationToken) 
        {
            var records = await _repo.GetS<T>();
            
            if (records == null)
            {
                return new ResponseDTO<T> 
                { 
                    IsSuccess = false, 
                    Message = "No records found" 
                };
            }

            return new ResponseDTO<T> { Data = records };
        }
    }
}

This makes your response type-safe and avoids returning null (which is bad practice for DTOs).

3. How to Pass Entity Data to MediatR

You have two common ways to work with entities in your MediatR queries:

Option 1: Pass Entity Type via Generic Parameter

You're already doing this correctly! The T in GetAllBaseQuery<T> defines the entity type your handler will fetch. Your repository's GetS<T>() method uses this type to retrieve the correct data.

Option 2: Pass Entity-Specific Parameters

If you need to send filtering, sorting, or entity instance data to the handler, add properties to your query class:

public class GetAllBaseQuery<T> : IRequest<IResponseDTO<T>> where T : class 
{
    // Example: Pass a filter entity for dynamic filtering
    public T FilterEntity { get; set; }

    // Example: Pass a search term for text-based filtering
    public string SearchTerm { get; set; }
}

Then use these parameters in your handler:

public async Task<IResponseDTO<T>> Handle(GetAllBaseQuery<T> query, CancellationToken cancellationToken) 
{
    // Use the filter entity or search term in your repository call
    var records = await _repo.GetS<T>(query.SearchTerm, query.FilterEntity);
    
    // ... rest of the handler logic
}

This lets you customize each query with entity-specific data while keeping the base class reusable.


内容的提问来源于stack exchange,提问作者Mohammed Emara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 10:12:29