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

Builder模式下HtmlElement的protected构造函数无法运行的解决方案问询

解决HtmlElement构造函数设为protected后无法运行的问题

protected 修饰的构造函数仅允许当前类自身、以及继承自当前类的子类访问。你现有代码中HtmlBuilder和HtmlElement是两个独立的平级类,没有继承关系,自然无法调用HtmlElement的受保护构造函数。

以下是两种可直接落地的解决方案:

方案1:将HtmlBuilder设为HtmlElement的嵌套类(推荐)

这是Builder模式的标准实现方式,你甚至可以把HtmlElement的构造函数直接设为private,完全禁止外部直接实例化HtmlElement,强制所有实例都通过Builder流程构建,访问控制精度最高。
修改后的完整代码如下:

void Main()
{
    var builder = HtmlElement.Create("div")
        .AddChild("li", "hello")
        .AddChild("li", "world");
    builder.ToString().Dump();
}

public class HtmlElement
{
    internal string Name { get; set; }
    internal string Text { get; set; }
    internal List<HtmlElement> Elements = new();
    
    // 构造函数直接设为private,完全禁止外部直接实例化
    private HtmlElement() { }
    private HtmlElement(string name, string text)
    {
        this.Name = name;
        this.Text = text;
    }
    
    public override string ToString()
    {
        var stringBuilder = new System.Text.StringBuilder();
        stringBuilder
            .Append($"<{Name}>")
            .Append($"{Text}");
            
        foreach (var elem in Elements)
        {
            stringBuilder
                .Append($"<{elem.Name}>")
                .Append($"{elem.Text}")
                .Append($"</{elem.Name}>");
        }
        stringBuilder.Append($"</{Name}>");
        return stringBuilder.ToString();
    }
    
    public static HtmlBuilder Create(string name) => new HtmlBuilder(name);   

    // HtmlBuilder作为嵌套类,可直接访问外层类的私有/受保护成员
    public class HtmlBuilder  
    {
        protected readonly string rootName;
        protected HtmlElement root = new();
        
        internal HtmlBuilder(string rootName) {
            this.rootName = rootName;
            this.root.Name = rootName;
        }
        
        public HtmlBuilder AddChild(string childName, string childText) {
            var elem = new HtmlElement(childName, childText);
            root.Elements.Add(elem);
            return this;
        }
     
        public override string ToString() => root.ToString();   
    }
}

方案2:让HtmlBuilder继承HtmlElement

如果你不希望调整现有代码的类结构,可以用继承的方式获得protected构造函数的访问权限:

  1. 保留HtmlElement构造函数的protected修饰
  2. 让HtmlBuilder类继承HtmlElement即可
    核心修改示例:
public class HtmlElement
{
    internal string Name { get; set; }
    internal string Text { get; set; }
    internal List<HtmlElement> Elements = new();
    
    // 保留protected修饰
    protected HtmlElement() { }
    protected HtmlElement(string name, string text)
    {
        this.Name = name;
        this.Text = text;
    }
    // 其余HtmlElement原有代码不变
}

// 仅新增继承HtmlElement即可
public class HtmlBuilder : HtmlElement
{
    protected readonly string rootName;
    protected HtmlElement root = new();
    
    internal HtmlBuilder(string rootName) {
        this.rootName = rootName;
        this.root.Name = rootName;
    }
    // 其余HtmlBuilder原有代码不变
}

方案对比

  • 方案1的类结构更合理,符合Builder模式的设计初衷,访问控制更严格,是生产环境的首选实现
  • 方案2的继承关系没有实际业务含义,仅适合临时调试、不想大幅调整代码结构的场景使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 14:27:01