gpt4 book ai didi

c# - 取消代币注入(inject)

转载 作者:行者123 更新时间:2023-12-04 13:12:01 28 4
gpt4 key购买 nike

我希望能够通过依赖注入(inject)而不是每次都作为参数传递取消 token 。这是一回事吗?
我们有一个 asp.net-core 2.1 应用程序,我们将来自 Controller 的调用传递到异步库、处理程序和其他服务的迷宫中,以满足我们服务的金融科技监管领域的拜占庭需求。
在请求的顶部,我可以声明我想要一个取消 token ,我会得到一个:

    [HttpPost]
public async Task<IActionResult> DoSomeComplexThingAsync(object thing, CancellationToken cancellationToken) {
await _someComplexLibrary.DoThisComplexThingAsync(thing, cancellationToken);
return Ok();
}
现在,我想成为一名优秀的异步程序员并确保我的 cancellationToken通过调用链向下传递到每个异步方法。我想确保它被传递给 EF、System.IO 流等。我们拥有您期望的所有常用存储库模式和消息传递实践。我们尽量保持我们的方法简洁,并有一个单一的责任。我的技术负责人显然被“福勒”这个词激怒了。所以我们的类大小和函数体很小,但我们的调用链非常非常深。
这意味着每一层、每一个功能都必须交出该死的 token :
    private readonly ISomething _something;
private readonly IRepository<WeirdType> _repository;

public SomeMessageHandler(ISomething<SomethingElse> something, IRepository<WeirdType> repository) {
_something = something;
_repository = repository;
}

public async Task<SomethingResult> Handle(ComplexThing request, CancellationToken cancellationToken) {
var result = await DoMyPart(cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
result.SomethingResult = await _something.DoSomethingElse(result, cancellationToken);
return result;
}

public async Task<SomethingResult> DoMyPart(ComplexSubThing request, CancellationToken cancellationToken) {
return await _repository.SomeEntityFrameworkThingEventually(request, cancellationToken);
}
根据我们域复杂性的需要,这无休止地进行下去。好像 CancellationToken在我们的代码库中出现的次数比任何其他术语都要多。我们的 arg 列表通常已经太长(即不止一个),即使我们声明了一百万个对象类型。现在我们在每个 arg 列表和每个方法 decl 中都有这个额外的小取消 token 伙伴。
我的问题是,由于 Kestrel 和/或管道首先给了我 token ,如果我能拥有这样的东西就好了:
    private readonly ISomething _something;
private readonly IRepository<WeirdType> _repository;
private readonly ICancellationToken _cancellationToken;

public SomeMessageHandler(ISomething<SomethingElse> something, ICancellationToken cancellationToken) {
_something = something;
_repository = repository;
_cancellationToken = cancellationToken;
}

public async Task<SomethingResult> Handle(ComplexThing request) {
var result = await DoMyPart(request);
_cancellationToken.ThrowIfCancellationRequested();
result.SomethingResult = await _something.DoSomethingElse(result);
return result;
}

public async Task<SomethingResult> DoMyPart(ComplexSubThing request) {
return await _repository.SomeEntityFrameworkThingEventually(request);
}
然后这将通过 DI 组合传递,当我有一些明确需要 token 的东西时,我可以这样做:
    private readonly IDatabaseContext _context;
private readonly ICancellationToken _cancellationToken;

public IDatabaseRepository(IDatabaseContext context, ICancellationToken cancellationToken) {
_context = context;
_cancellationToken = cancellationToken;
}

public async Task<SomethingResult> DoDatabaseThing() {
return await _context.EntityFrameworkThing(_cancellationToken);
}
我疯了吗?我是不是每时每刻都传递该死的 token ,并为所给予的赏金赞美异步众神?我应该重新培训成为 Camel 农民吗?他们看起来不错。甚至问这是某种异端邪说吗?我现在应该忏悔吗?我认为要使 async/await 正常工作, token 必须在 func decl 中。所以,也许是 Camel

最佳答案

我认为你的想法很好,我认为你不需要后悔或忏悔。
这是个好主意,我也考虑过,我实现了自己的解决方案

public abstract class RequestCancellationBase
{
public abstract CancellationToken Token { get; }

public static implicit operator CancellationToken(RequestCancellationBase requestCancellation) =>
requestCancellation.Token;
}


public class RequestCancellation : RequestCancellationBase
{
private readonly IHttpContextAccessor _context;

public RequestCancellation(IHttpContextAccessor context)
{
_context = context;
}

public override CancellationToken Token => _context.HttpContext.RequestAborted;
}
并且注册应该是这样的
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<RequestCancellationBase, RequestCancellation>();
现在你可以注入(inject) RequestCancellationBase任何你想要的地方,更好的是你可以直接将它传递给每个需要 CancellationToken 的方法。这是因为 public static implicit operator CancellationToken(RequestCancellationBase requestCancellation)这个解决方案帮助了我,希望它也对你有帮助

关于c# - 取消代币注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64122616/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com