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构造函数的访问权限:
- 保留HtmlElement构造函数的
protected修饰 - 让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
相关产品推荐
相关产品推荐

