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.