You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让C#建造者模式实现接口后仍保留链式调用能力?

可通过接口扩展的链式建造者模式实现方案

问题描述

需要实现一个通过多接口扩展功能的建造者模式,要求调用任意接口方法后,返回的对象仍能链式调用所有实现的接口方法。当前代码中,调用BuilderCapability()后返回的是IBuilder<int, string>类型,无法直接链式调用AdditionalBuilderFeature()方法。

原始问题代码:

namespace BuilderChaining
{
    internal interface IBuilder<A, B>
    {
        IBuilder<A, B> BuilderCapability();
    }

    internal interface IConsumeOtherBuilder<A, B, C>
    {
        IConsumeOtherBuilder<A, B, C> AdditionalBuilderFeature(IBuilder<B, C> obj);
    }

    internal class ExampleBuilder : IBuilder<int, string>, IConsumeOtherBuilder<int, string, object>, IConsumeOtherBuilder<Guid, object, int>
    {
        public IConsumeOtherBuilder<int, string, object> AdditionalBuilderFeature(IBuilder<string, object> obj)
        {
            return this;
        }

        public IConsumeOtherBuilder<Guid, object, int> AdditionalBuilderFeature(IBuilder<object, int> obj)
        {
            return this;
        }

        public IBuilder<int, string> BuilderCapability()
        {
            return this;
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            var builder = new ExampleBuilder();

            builder.BuilderCapability() // 此处无法继续链式调用AdditionalBuilderFeature()
                .AdditionalBuilderFeature(/*Some param value*/)
                .AdditionalBuilderFeature(/*Some param value*/);
        }
    }
}

现有尝试的缺陷

曾尝试通过泛型Self参数解决,但该方案需要每次调用方法时显式指定返回类型,易用性差,且会触发空引用返回警告:

// 简化后的问题代码片段
internal interface IBuilder<A, B>
{
    Self BuilderCapability<Self>() where Self : class, IBuilder<A, B>;
}

// 调用时必须指定泛型类型
builder.BuilderCapability<ExampleBuilder>()
    .AdditionalBuilderFeature<ExampleBuilder>(new OtherBuilders<string, object>());

最优解决方案:递归泛型约束

通过给每个接口添加递归泛型约束,让接口方法直接返回具体的建造者实现类,从而保留完整的类型信息,支持无额外指定的链式调用。

1. 修改接口定义

为每个接口添加Self泛型参数,约束为当前接口的实现类:

internal interface IBuilder<A, B, out Self> 
    where Self : IBuilder<A, B, Self>
{
    Self BuilderCapability();
}

internal interface IConsumeOtherBuilder<A, B, C, out Self> 
    where Self : IConsumeOtherBuilder<A, B, C, Self>
{
    Self AdditionalBuilderFeature(IBuilder<B, C, object> obj);
}

2. 实现建造者类

让ExampleBuilder实现接口时,将Self参数指定为自身,所有方法返回ExampleBuilder类型:

internal class ExampleBuilder : 
    IBuilder<int, string, ExampleBuilder>, 
    IConsumeOtherBuilder<int, string, object, ExampleBuilder>, 
    IConsumeOtherBuilder<Guid, object, int, ExampleBuilder>
{
    public ExampleBuilder AdditionalBuilderFeature(IBuilder<string, object, object> obj)
    {
        // 此处添加业务逻辑
        return this;
    }

    public ExampleBuilder AdditionalBuilderFeature(IBuilder<object, int, object> obj)
    {
        // 此处添加业务逻辑
        return this;
    }

    public ExampleBuilder BuilderCapability()
    {
        // 此处添加业务逻辑
        return this;
    }
}

3. 实现辅助建造者类

其他辅助建造者同样遵循接口约束:

internal class OtherBuilders<A, B> : IBuilder<A, B, OtherBuilders<A, B>>
{
    public OtherBuilders<A, B> BuilderCapability()
    {
        // 此处添加业务逻辑
        return this;
    }
}

4. 链式调用示例

此时可以直接实现无额外泛型指定的链式调用:

internal class Program
{
    static void Main(string[] args)
    {
        var builder = new ExampleBuilder();

        builder.BuilderCapability()
            .AdditionalBuilderFeature(new OtherBuilders<string, object>())
            .AdditionalBuilderFeature(new OtherBuilders<object, int>());
    }
}

方案优势

  • 无需显式指定泛型类型,调用体验简洁
  • 所有方法返回具体建造者类,保留完整的方法调用能力
  • 符合测试数据构建的场景需求,即使是测试专用方案也足够优雅

内容的提问来源于stack exchange,提问作者PurpleKoala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:10:55