作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望能够通过依赖注入(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 流等。我们拥有您期望的所有常用存储库模式和消息传递实践。我们尽量保持我们的方法简洁,并有一个单一的责任。我的技术负责人显然被“福勒”这个词激怒了。所以我们的类大小和函数体很小,但我们的调用链非常非常深。
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 伙伴。
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/
我是一名优秀的程序员,十分优秀!