具有自定义返回类型的通用CQRS查询处理程序

问题描述 投票:1回答:1

我正在尝试使用MediatR(v8)库构建通用查询处理程序。让我们跳到代码:首先,我有一个像这样的抽象查询类:

public abstract class Query<TQueryResult> : IRequest<TQueryResult>
{
    public Guid Id { get; } = Guid.NewGuid();

    public DateTime Timestamp { get; }

    protected Query()
    {
        Timestamp = DateTime.Now;
    }
}

从相应的查询处理程序中,我想返回一个Result包装对象,其外观如下:

public class Result<T> 
{
    public T Payload { get;  }
    public string FailureReason { get;  }

    public bool IsSuccess => FailureReason == null;

    public Result(T payload)
    {
        Payload = payload;
    }

    public Result(string failureReason)
    {
        FailureReason = failureReason;
    }

    public static Result<T> Success(T payload)
        => new Result<T>(payload);

    public static Result<T> Failure(string reason)
        => new Result<T>(reason);

    public static implicit operator bool(Result<T> result) => result.IsSuccess;

}

最后但并非最不重要的一点,让我们看一下查询处理程序:

public abstract class AbstractQueryHandler<TQuery, TQueryResult, TResultValue> : IRequestHandler<TQuery, TQueryResult>
    where TQuery : Query<TQueryResult>
    where TQueryResult : class
{

    public Task<TQueryResult> Handle(TQuery request, CancellationToken cancellationToken)
    {
        try
        {
            return HandleQuery(request);
        }
        catch (Exception e)
        {
            return Task.FromResult(Result<TResultValue>.Failure(GetFailureMessage(e)) as TQueryResult);
        }
    }

    public abstract Task<TQueryResult> HandleQuery(TQuery request);

    private static string GetFailureMessage(Exception e)
    {
        return "There was an error while executing query: \r\n" + e.Message;
    }
}

老实说,由于我在查询处理程序中具有三个类型参数,因此我对这种解决方案不满意。让我们看一些相应的测试来揭示我的担忧。首先是测试助手对象:

public class ExampleDto 
{
    public string Name { get; set; }
}

public class BasicQuery : Query<Result<ExampleDto>>
{

}

public class BasicQueryHandler : AbstractQueryHandler<BasicQuery, Result<ExampleDto>, ExampleDto>
{
    public override Task<Result<ExampleDto>> HandleQuery(BasicQuery request)
    {
        return Task.FromResult(Result<ExampleDto>.Success(new ExampleDto() { Name = "Result Name" }));
    }
}

然后是测试:

    [Fact]
    public async Task GivenBasicQuery_whenHandle_thenSuccessResultWithPayload()
    {
        var handler = new BasicQueryHandler();

        var result = await handler.Handle(new BasicQuery(), CancellationToken.None);

        Check.That(result.IsSuccess).IsTrue();
        Check.That(result.Payload.Name).IsEqualToValue("Result Name");
    }

正如您在BasicQueryHandler中所看到的,在声明三种类型即<BasicQuery, Result<ExampleDto>, ExampleDto>时存在某种重复。在我看来真的很可疑。我还尝试了许多其他可能性,在Internet上检查文章和SO问题/答案,但无法提出更干净的解决方案。我究竟做错了什么?是否可以将(查询处理程序的)类型参数的数量减少到2?预先感谢您的帮助!

c# .net generics cqrs mediatr
1个回答
0
投票

基本上,我将Result <>从类声明中的类型参数移到了方法声明。为了清楚起见,我也删除了接口(无论如何您都没有共享定义)。

© www.soinside.com 2019 - 2024. All rights reserved.