0

I'm reading a book in Design Patterns, and below is some code example used by the author. The author tries to build a html builder as (code in C#):

public class HtmlElement
{
    public string Name, Text;
    public List<HtmlElement> Elements = new List<HtmlElement>();

    public HtmlElement() { }
    public HtmlElement(string name, string text)
    {
        Name = name;
        Text = text;
    }
    // factory method
    public static HtmlBuilder Create(string name)
    {
       return new HtmlBuilder(name);
    } 
}

//builder class
public class HtmlBuilder
{
    protected readonly string rootName;
    protected HtmlElement root = new HtmlElement();
    public HtmlBuilder(string rootName)
    {
        this.rootName = rootName;
        root.Name = rootName;
    }
    public HtmlBuilder AddChild(string childName, string childText)
    {
        var e = new HtmlElement(childName, childText);
        root.Elements.Add(e);
        return this;            //fluent api
    }

     // to return a HtmlElement object
    public static implicit operator HtmlElement(HtmlBuilder builder)
    {
        return builder.root;
    }
    public override string ToString() => root.ToString();
}

then the author says:

"To simply force users to use the Builder whenever they are constructing a HtmlElement object, we have hidden all constructors of HtmlElement class as":

public class HtmlElement
{
   ...
   protected HtmlElement() { }
   protected HtmlElement(string name, string text)
   {
      Name = name;
      Text = text;
   }
   ...
}

so users can go like

HtmlElement root = HtmlElement.Create("ul").AddChildFluent("li", "hello").AddChildFluent("li", "world");

Console.WriteLine(root);

here is what I don't understand, the author changed the access modifier of HtmlElement's constructors to protected, which means that HtmlBuilder class cannot access to the protected constructors like

protected HtmlElement root = new HtmlElement();    // not allowed

so does it mean that we need to let the HtmlBuilder inherit from HtmlElement? But they are no inheritance context at all, so how can I modify it?

1
  • Your sample still has public access modifiers
    – Fabio
    Sep 2, 2019 at 9:04

1 Answer 1

2

If you don't need the class to be inherited from outside your library, you can use internal, which will only allow it to be accessed within the same assembly.

If inheritance is required, you can use protected internal instead (see C# docs)

The protected internal keyword combination is a member access modifier. A protected internal member is accessible from the current assembly or from types that are derived from the containing class. For a comparison of protected internal with the other access modifiers, see Accessibility Levels.

This makes it accessible within the assembly, but not from outside it.

And if you want to prevent inheritance outside of your assembly, you can use private protected (see C# docs).

The private protected keyword combination is a member access modifier. A private protected member is accessible by types derived from the containing class, but only within its containing assembly. For a comparison of private protected with the other access modifiers, see Accessibility Levels.

Which allows you to inherit it in your assembly, but have the constructors private outside the assembly. Requires C# 7.2 compiler

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.