Help Content Targeting – tagging at a class level

Back in GhostDoc v4.7 we made available Help Content Targeting - the ability to create (partial) ‘filtered’ help files based on attributes by using <tags/> in XML Comments and tag filtering in Help Configuration. This was intended to cover the scenarios when you need to have different help content for public API users, testers, internal documentation, etc.

Here is an example of explicitly tagged of class members (simplified syntax for clarity):

public class MyClass /// <tags>API;Internal</tags> private string _myString; public string MyProperty(); /// <tags>API</tags> public void MyMethod()

When filtering by tag 'API', both the private field _myString and public method MyMethod will be included in the help documentation, but not the public property MyProperty.

Introducing tagging at a class level

With the v5.0 release of GhostDoc, we are extending the tagging to the class level. This will simplify the help content targeting of the complete class by not having to add explicit attributes to each of its members.

Starting with GhostDoc v5.0, you can tag at a class level which will implicitly tag all members of that class and enable them for help content targeting.

Here is example of implicitly and explicitly tagged class members using the new syntax (simplified syntax for clarity):

/// <tags>API</tags> public class MyClass /// <tags>API;Internal</tags> private string _myString; public string MyProperty(); /// <tags>API</tags> public void MyMethod()

With this new syntax, the help configuration Scope targeting has the following logic:

(	
  ( Scope:
    public|internal|protected|private|inherited|inherited_from_refrences )
  AND
  ( Tagged with: {tag} (implicitly) )
)
OR
(
  Tagged with: {tag} (explicitly)
)

Example 1. Scope and implicitly tagged class members

/// <summary> /// Summary description for Employee. /// </summary> public class Employee { /// <summary> /// Employee's salary /// </summary> private Decimal _salary; /// <summary> /// Gets the salary. /// </summary> /// <value>The salary value.</value> public Decimal Salary { get { return _salary; } } } /// <summary> /// Summary description for Person. /// </summary> /// <tags>API</tags> public class Person { /// <summary> /// Person's first name /// </summary> private string _firstName; /// <summary> /// Person's last name /// </summary> private string _lastName; /// <summary> /// Initializes a new instance of the <see cref="Person"/> class. /// </summary> /// <param name="firstName">The first name.</param> /// <param name="lastName">The last name.</param> /// <param name="email">The email.</param> public Person(string firstName, string lastName, string email) { this._firstName = firstName; this._lastName = lastName; this._email = email; } /// <summary> /// Returns the full name. /// </summary> /// <returns>System.String.</returns> public virtual string GetFullName() { return _firstName + " " + _lastName; } }

Help file will include:

public class Person public Person(string firstName, string lastName, string email) public virtual string GetFullName()

The Class Person constructor and GetFullName method are included in the help documentation because they are public AND implicitly tagged with 'API'.

Class Employee is not included because it is not tagged.

Example 2. Scope and both implicitly and explicitly tagged class members

/// <summary> /// Summary description for Person. /// </summary> /// <tags>API</tags> public class Person { /// <summary> /// Person's first name /// </summary> /// <tags>API</tags> private string _firstName; /// <summary> /// Person's last name /// </summary> private string _lastName; /// <summary> /// Initializes a new instance of the <see cref="Person"/> class. /// </summary> /// <param name="firstName">The first name.</param> /// <param name="lastName">The last name.</param> /// <param name="email">The email.</param> public Person(string firstName, string lastName, string email) { this._firstName = firstName; this._lastName = lastName; this._email = email; } /// <summary> /// Returns the full name. /// </summary> /// <returns>System.String.</returns> public virtual string GetFullName() { return _firstName + " " + _lastName; } }

(the difference between this and example 1 is that private field _firstName is now tagged with 'API')

Help file will include:

public class Person private string _firstName public Person(string firstName, string lastName, string email) public virtual string GetFullName()

Class Person constructor and method GetFullName are included in the help documentation because they are public AND implicitly tagged with 'API'.

Private field _firstName is also included, even though it is not public because it is explicitly tagged with 'API'.

Example 3. Scope - public and private members

/// <summary> /// Summary description for Person. /// </summary> /// <tags>API</tags> public class Person { /// <summary> /// Person's first name /// </summary> /// <tags>API</tags> private string _firstName; /// <summary> /// Person's last name /// </summary> private string _lastName; /// <summary> /// Initializes a new instance of the <see cref="Person"/> class. /// </summary> /// <param name="firstName">The first name.</param> /// <param name="lastName">The last name.</param> /// <param name="email">The email.</param> public Person(string firstName, string lastName, string email) { this._firstName = firstName; this._lastName = lastName; this._email = email; } /// <summary> /// Returns the full name. /// </summary> /// <returns>System.String.</returns> public virtual string GetFullName() { return _firstName + " " + _lastName; } }

(The difference between this and Example 2 is that we now also include private members)

Help file will include:

public class Person private string _firstName private string _lastName public Person(string firstName, string lastName, string email) public virtual string GetFullName()

All public and private class members are included because they are implicitly tagged with 'API' at the class level.

Example 4. Nested classes

/// <summary> /// Class A. /// </summary> /// <tags>API</tags> public class A { /// <summary> /// Class AA. /// </summary> public class AA { /// <summary> /// Class AAA. /// </summary> public class AAA { /// <summary> /// Initializes a new instance of the <see cref="AAA"/> class. /// </summary> public AAA() { } } /// <summary> /// Initializes a new instance of the <see cref="AA"/> class. /// </summary> public AA() { } } /// <summary> /// Initializes a new instance of the <see cref="A"/> class. /// </summary> public A() { } }

Help file will include:

public class A public A() public class AA public AA() public class AAA public AAA()

Because AA and AAA classes are nested inside Class A, they will be included in the Help file.