如何在Fluent Builder中集成异步方法且不破坏链式调用?
在Fluent Builder中集成异步方法且不破坏链式调用的解决方案
当你需要在Fluent Builder中加入异步操作(比如示例里的邮箱验证逻辑),但又不想打破原有链式调用的流畅性时,可以参考以下几种落地方案:
方案一:拆分同步/异步Builder类
创建一个异步版本的Builder类,同步方法返回异步Builder,异步方法也返回异步Builder,最后通过Build方法完成对象构建。这种方式能保持调用链的连贯性,同时明确区分同步和异步操作边界。
public class Email { public string From { get; set; } public string To { get; set; } public string Body { get; set; } } public class EmailBuilder { protected readonly Email _email; public EmailBuilder() { _email = new Email(); } // 同步方法返回异步Builder,衔接后续异步操作 public AsyncEmailBuilder From(string from) { _email.From = from; return new AsyncEmailBuilder(_email); } public AsyncEmailBuilder Body(string body) { _email.Body = body; return new AsyncEmailBuilder(_email); } } public class AsyncEmailBuilder { protected readonly Email _email; public AsyncEmailBuilder(Email email) { _email = email; } // 异步方法返回自身,保持链式调用 public async Task<AsyncEmailBuilder> To(string to) { if (await VerifyAsync(to)) { _email.To = to; } return this; } // 异步Builder也支持同步方法 public AsyncEmailBuilder Body(string body) { _email.Body = body; return this; } // 最终构建目标对象 public Email Build() { return _email; } } // 模拟异步邮箱验证方法 private static async Task<bool> VerifyAsync(string email) { // 替换为实际验证逻辑 await Task.Delay(100); return true; }
调用示例:
var email = await new EmailBuilder() .From("foo@bar.com") .To("bar@baz.com") .Body("Hello, how are you?") .Build(); ms.SendEmail(email);
方案二:用扩展方法包装异步操作
如果不想改动原有同步Builder的结构,可以通过扩展方法封装异步逻辑,尽量保留原有链式调用的流畅性。需要注意的是,异步操作需要单独await,之后可继续调用同步方法。
public class Email { public string From { get; set; } public string To { get; set; } public string Body { get; set; } } public class EmailBuilder { private readonly Email _email = new Email(); public EmailBuilder From(string from) { _email.From = from; return this; } public EmailBuilder Body(string body) { _email.Body = body; return this; } public Email Build() => _email; // 内部暴露Email对象给扩展方法(同一程序集内建议设为internal访问) internal Email GetEmail() => _email; } public static class EmailBuilderAsyncExtensions { public static async Task<EmailBuilder> ToAsync(this EmailBuilder builder, string to) { if (await VerifyAsync(to)) { builder.GetEmail().To = to; } return builder; } private static async Task<bool> VerifyAsync(string email) { await Task.Delay(100); return true; } }
调用示例:
var builder = new EmailBuilder() .From("foo@bar.com"); // 单独await异步验证操作 await builder.ToAsync("bar@baz.com"); // 继续调用同步方法完成构建 var email = builder.Body("Hello, how are you?").Build(); ms.SendEmail(email);
方案三:全异步化Builder
直接将所有Builder方法统一改为返回Task<EmailBuilder>,同步方法用Task.FromResult(this)包装,这样整个调用链都可以用await衔接,完全保持链式调用的流畅性。
public class Email { public string From { get; set; } public string To { get; set; } public string Body { get; set; } } public class EmailBuilder { private readonly Email _email = new Email(); public Task<EmailBuilder> From(string from) { _email.From = from; return Task.FromResult(this); } public async Task<EmailBuilder> To(string to) { if (await VerifyAsync(to)) { _email.To = to; } return this; } public Task<EmailBuilder> Body(string body) { _email.Body = body; return Task.FromResult(this); } public Email Build() => _email; } private static async Task<bool> VerifyAsync(string email) { await Task.Delay(100); return true; }
调用示例:
var email = await new EmailBuilder() .From("foo@bar.com") .To("bar@baz.com") .Body("Hello, how are you?") .Build(); ms.SendEmail(email);
方案选型建议
- 方案一:适合新开发的Builder,结构清晰、同步异步边界明确,调用体验好,但需要维护两个Builder类。
- 方案二:适合改造已有同步Builder,侵入性低,但调用时需要拆分异步操作,连贯性稍差。
- 方案三:适合以异步操作为主的场景,调用链完全连贯,但同步方法需要包装成Task,略显冗余。
内容的提问来源于stack exchange,提问作者Odmilson Maestri Jr
相关产品推荐
相关产品推荐

