将async Tasks与构建器模式一起使用

Col*_*con 13 .net c# asynchronous builder async-await

我目前使用构建器模式来构建我的MVC视图模型.

var viewModel = builder
                  .WithCarousel(),
                  .WithFeaturedItems(3),
                  .Build()
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是当我必须对异步方法进行服务调用时.这意味着我的构建器方法必须返回Task<HomeViewModelBuilder>而不是HomeViewModelBuilder.这可以防止我像我一样链接构建方法await.

示例方法

public async Task<HomeViewModelBuilder> WithCarousel()
{   
    var carouselItems = await _service.GetAsync();
    _viewModel.Carousel = carouselItems;
    return this;
}
Run Code Online (Sandbox Code Playgroud)

现在我必须使用await调用构建器方法.

await builder.WithCarousel();
await builder.WithFeaturedItems(3);
Run Code Online (Sandbox Code Playgroud)

有没有人使用构建器模式的异步方法?如果是这样,是否可以链接方法或推迟await构建方法.

Ste*_*ary 6

我以前实际上并没有做过,但是这是Sriram解决方案的替代方案。

想法是捕获构建器对象中的任务,而不是捕获任务的结果。Build然后,该方法等待它们完成并返回构造的对象。

public sealed class HomeViewModelBuilder
{
  // Example async
  private Task<Carousel> _carouselTask = Task.FromResult<Carousel>(null);
  public HomeViewModelBuilder WithCarousel()
  {
    _carouselTask = _service.GetAsync();
    return this;
  }

  // Example sync
  private int _featuredItems;
  public HomeViewModelBuilder WithFeaturedItems(int featuredItems)
  {
    _featuredItems = featuredItems;
    return this;
  }

  public async Task<HomeViewModel> BuildAsync()
  {
    return new HomeViewModel(await _carouselTask, _featuredItems);
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

var viewModel = await builder
    .WithCarousel(),
    .WithFeaturedItems(3),
    .BuildAsync();
Run Code Online (Sandbox Code Playgroud)

此构建器模式可用于任意数量的异步或同步方法,例如:

public sealed class HomeViewModelBuilder
{
  private Task<Carousel> _carouselTask = Task.FromResult<Carousel>(null);
  public HomeViewModelBuilder WithCarousel()
  {
    _carouselTask = _service.GetAsync();
    return this;
  }

  private Task<int> _featuredItemsTask;
  public HomeViewModelBuilder WithFeaturedItems(int featuredItems)
  {
    _featuredItemsTask = _featuredService.GetAsync(featuredItems);
    return this;
  }

  public async Task<HomeViewModel> BuildAsync()
  {
    return new HomeViewModel(await _carouselTask, await _featuredItemsTask);
  }
}
Run Code Online (Sandbox Code Playgroud)

用法还是一样。

  • @ColinBacon:我不确定你的意思;您可以使用相同的模式进行任意数量的异步构建器调用。 (2认同)

Sri*_*vel 5

正如我在评论中所说,您可以为其编写Extension方法HomeViewModelBuilder以及将Task<HomeViewModelBuilder>其链接。

public static class HomeViewModelBuilderExtension
{
    public static Task<HomeViewModelBuilder> WithCarousel(this HomeViewModelBuilder antecedent)
    {
        return WithCarousel(Task.FromResult(antecedent));
    }

    public static async Task<HomeViewModelBuilder> WithCarousel(this Task<HomeViewModelBuilder> antecedent)
    {
        var builder = await antecedent;
        var carouselItems = await builder.Service.GetAsync();
        builder.ViewModel.Carousel = carouselItems;
        return builder;
    }

    public static Task<HomeViewModelBuilder> WithFeaturedItems(this HomeViewModelBuilder antecedent, int number)
    {
        return WithFeaturedItems(Task.FromResult(antecedent), number);
    }

    public static async Task<HomeViewModelBuilder> WithFeaturedItems(this Task<HomeViewModelBuilder> antecedent, int number)
    {
        var builder = await antecedent;
        builder.ViewModel.FeaturedItems = number;
        return builder;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们为单一操作添加了几种方法,以便您可以将其与 HomeViewModelBuilder或链接Task<HomeViewModelBuilder>。否则您将无法打电话builder.WithCarousel()

然后像

private static void Main()
{
    HomeViewModelBuilder builder = new HomeViewModelBuilder();
    var task = builder
        .WithCarousel()
        .WithFeaturedItems(3);        
}
Run Code Online (Sandbox Code Playgroud)