It is true that if you start using async-await it spreads as a zombie along application pipeline and you will be forced to use async everywhere.
Try to approach design from a bit different angle - domain logic care only about data.
So we can put all IO related code outside of domain layers as close to the top layers as possible.
1 Load required data asynchronouslyasynchronously
2 Pass data to the business logic
3 Process data synchronouslysynchronously
4 Return possible results
5 Save processed results asynchronouslyasynchronously
public class MyDomainObject
{
public MyDomainObject(DomainContent content) => _content = content;
public ProcessedContent DoSomething()
{
// Process given content
}
}
// This implementation belongs to the "infrastructure" layer
public class MyDomainProcessor
{
public MyDomainProcessor(IContentRepository repository)
{
_repository = repository;
}
public async Task ProcessAsync(Guid contentId)
{
var content = await _repository.GetContentBy(contentId);
var processedContent = new MyDomainObject(content).DoSomething();
await _repository.Save(processedContent);
}
}