How to autocorrect xml documentation of methods - c#

In the below code in xml documentations there is mismatch between the names of parameters in method's arguments and name of parameters in xml documentation. Is there any way to auto correct the xml documentation signature or any feature provided in resharper to auto correct the xml documentation.
#region Get Images
/// <summary>
/// Get Images
/// </summary>
/// <param name="par1"></param>
/// <param name="par2"></param>
/// <returns></returns>
public Collection<UserImage> GetImages()
{
return GetImages("");
}
/// <summary>
/// Get Images
/// </summary>
/// <param name="par1"></param>
/// <param name="par2"></param>
/// <returns></returns>
public Collection<UserImage> GetImages(string imageType)
{
return GetImages(0, imageType);
}
/// <summary>
/// Get Images
/// </summary>
/// <param name="par1"></param>
/// <param name="par2"></param>
/// <returns></returns>
public Collection<UserImage> GetImages(int imageId)
{
return GetImages(imageId, "");
}
/// <summary>
/// Get Images
/// </summary>
/// <param name="par1"></param>
/// <param name="par2"></param>
/// <returns></returns>
public Collection<UserImage> GetImages(int imageId,string imageType)
{
return null;
}
#endregion
For example i want the method with xml documentation like this:
/// <summary>
/// Get Images
/// </summary>
/// <param name="imageId"></param>
/// <param name="imageType"></param>
/// <returns></returns>
public Collection<UserImage> GetImages(int imageId,string imageType)
{
return null;
}
#endregion

GhostDoc will do this for you. After installation you get a new context menu item in VS 'Document this' (and a corresponding keyboard shortcut).
If no XML comments are present, it will add them. If they are already present, they should get updated as you require.
http://submain.com/products/ghostdoc.aspx

The only way I know to "auto correct" xml with R# is to delete the existing xml documentation and hit /// again. Sorry I don't have a better answer.
I believe it's not possible because R# doesn't what need to correct the xml documentation or method signature.

Related

C# method parameter XML-documentation issue

Assume, i have a method which parameters are classes with already defined documentation:
/// <summary>
/// Get criterion from table.
/// </summary>
/// <param name="plySide"></param>
/// <param name="criterionType"></param>
/// <returns></returns>
public Criterion GetCriterion(PlySide plySide, CriterionType criterionType)
{
// some code
}
PlySide class has it's own xml-documentation:
/// <summary>
/// Sides of monoply.
/// </summary>
public enum PlySide
{
// some code
}
As you can see in GetCriterion method i didn't define any doc for the plySide param tag.
My question is should i duplicate description of a parameter or should i remove param tags?
The PlySide documentation will describe what the type is.
The plySide documentation should describe what role that parameter plays within the GetCriterion method.
Those will usually be subtly (or not so subtly) different.
You shouldn't duplicate it but give a context aware description of the parameter. In your case it could be something like this (perhaps it's toally wrong, but I don't know the implementation and intention of your method):
/// <summary>
/// Get criterion from table.
/// </summary>
/// <param name="plySide">Monopoly side to get criterion for</param>
/// <param name="criterionType">Criterion to get for the given monopoly side</param>
/// <returns></returns>
public Criterion GetCriterion(PlySide plySide, CriterionType criterionType)
{
// some code
}

In C# XML comments, can you detail the type a List<T> contains?

Currently I'm documenting Lists as follows:
/// <summary>
/// Returns a <see cref="List{T}" /> of type <see cref="Person" />.
/// </summary>
public List<Person> ListExample()
{
}
The following does not seem to be interpreted by Sandcastle:
/// <summary>
/// Returns a <see cref="List{Person}" />.
/// </summary>
public List<Person> ListExample()
{
}
Any advice?
Thanks.

How do I reference method parameters in a method summary when writing XML documentation?

Suppose I have a method as follows:
/// <summary>
/// Here I want to reference the parameter <see cref="personId"/>.
/// </summary>
/// <param name="personId">
/// The person id.
/// </param>
/// <returns>
/// The <see cref="Person"/>.
/// </returns>
public Person GetPerson(int personId)
{
}
When I publish my XML documentation using Sandcastle, the cref:
<see cref="personId"/>
gets converted to [!:personId].
The warning in Sandcastle is:
Unknown reference link target
Any advice?
Use <paramref>
<paramref name="personId"/>

C# Fluent API: How to construct

Currently, I'm creating custom MVC Html Helpers which I will be using through a fluent API.
To give an example to understand it, I'll have the following helper which is (or should be in a not too distant future) generate a grid:
#(Html.GridFor(Model)
.WithName("MyName")
.WithColumns(model =>
{
model.Bind(x => x.Name);
model.Bind(x => x.DateCreated);
model.Bind(x => x.DateUpdated);
}).Render());
Now, everything is constructed with the start point. The IGridBuilder.
/// <summary>
/// When implemented by a class, it defines the class as an object that can construct a grid by using a fluent API.
/// </summary>
public interface IGridBuilder<TModel> : IHtmlHelper, IDataSource<TModel>
{
#region Properties
/// <summary>
/// Gets the name of the <see cref="IGridBuilder{TModel}" />.
/// </summary>
string Name { get; }
#endregion
#region Methods
/// <summary>
/// Sets the name of the <see cref="IGridBuilder{TModel}" />. This name will be used as an id on the outer element that
/// holds the entire grid.
/// </summary>
/// <param name="name">The name that the <see cref="IGridBuilder{TModel}" /> should have.</param>
/// <returns>An <see cref="IGridBuilder{TModel}" /> that can be used to construct the grid through a fluent API.</returns>
IGridBuilder<TModel> WithName(string name);
/// <summary>
/// Set the columns of the model that should be bound to grid.
/// </summary>
/// <param name="bindAllColumns">The action that will bind all the columns.</param>
/// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
IGridBuilder<TModel> WithColumns(Action<IColumnBinder<TModel>> bindAllColumns);
/// <summary>
/// Renders the grid with all the set properties.
/// </summary>
/// <returns>A <see cref="MvcHtmlString" /> that contains the HTML representation of the grid.</returns>
MvcHtmlString Render();
#endregion
}
and to make the bind commands, I'm using an IColumnBinder interface:
/// <summary>
/// When implemented by a class, this class is marked as being an builder that can construct a column through a fluent API.
/// </summary>
/// <typeparam name="TModel"></typeparam>
public interface IColumnBinder<TModel> : IHtmlHelper, IDataSource<TModel>
{
#region Methods
/// <summary>
/// Binds an column to the grid.
/// </summary>
/// <typeparam name="TItem">The type of the column on which to bind the items.</typeparam>
/// <param name="propertySelector">The functional that will bind the control to the grid.</param>
void Bind<TItem>(Expression<Func<TModel, TItem>> propertySelector);
/// <summary>
/// Apply a specific css class on an element.
/// </summary>
/// <param name="className">The name of the css class that should be placed on the element.</param>
/// <returns>As <see cref="IColumnBinder{TModel}"/> that is used to construct this column through a fluent API.</returns>
IColumnBinder<TModel> WithCss(string className);
#endregion
}
Now, what's the best approach to link an IColumnBuilder to an IGridBuilder?
To make it very short, I'm struggling with the following:
The IColumnBuilder set ups specific properties but the rendering takes place in the IGridBuilder interface.
The main problem lies in the following code:
/// <summary>
/// Set the columns of the model that should be bound to grid.
/// </summary>
/// <param name="bindAllColumns">The action that will bind all the columns.</param>
/// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
public IGridBuilder<TModel> WithColumns(Action<IColumnBinder<TModel>> bindAllColumns)
{
bindAllColumns(new ColumnBinder<TModel>());
return this;
}
So here I execute the action to bind the column:
model.Bind(x => x.Name)
But how can I keep a reference between the IGridBuilder and the IColumnBuilder to construct it in a proper way afterwars?
Or are there other solutions?
Ok,
After hours of searching I've found a solution and therefore I'm answering my own question. However, if there are users that have another approach to the same problem, please tell me so I can adapt me code maybe.
This code will primarly use a class to transfer objects, since a class is a reference type it can be passed to another object, and that object can manipulate the object.
So, I have written a custom HTML helper that should work as the following:
#(Html.GridFor(Model)
.WithName("MyName")
.WithColumns(model =>
{
model.Bind(x => x.Name).WithCss("row first");
model.Bind(x => x.DateCreated);
model.Bind(x => x.DateUpdated);
}).Render());
So, I do have a model that's enumerable and that I will pass to the grid. The grid takes 3 columns of the model and renders the grid.
For this code, I have a couple of interfaces which helps me throughout the process:
An HTML Helper interface (just holds an object to the HtmlHelper):
/// <summary>
/// Provides a way to extend the <see cref="HtmlHelper" /> to construct objects of various kinds.
/// </summary>
public static class HtmlHelperExtensions
{
#region Grid
/// <summary>
/// Constructs a grid for a property that holds a collection.
/// </summary>
/// <typeparam name="TModel">The type of the model on which this grid is being build.</typeparam>
/// <typeparam name="TEntity">The type of a single item in the collection. </typeparam>
/// <param name="htmlHelper">The helper on which this method is executed. </param>
/// <param name="dataSource">The datasource on which the items are bound. </param>
/// <returns>An <see cref="IGridBuilder{TEntity}" /> that is used to construct the grid.</returns>
public static IGridBuilder<TEntity> GridFor<TModel, TEntity>(this HtmlHelper<TModel> htmlHelper,
IEnumerable<TEntity> dataSource)
{
return new GridBuilder<TEntity>(htmlHelper, dataSource);
}
#endregion
}
A Datasource interface (just holds an interface to the datasource):
public interface IDataSource<out TModel>
{
#region Properties
/// <summary>
/// Gets the source that will be bound to the implemented object.
/// </summary>
IEnumerable<TModel> DataSource { get; }
#endregion
}
And then we have all the other code.
The HTML Helper extension class is the first one:
/// <summary>
/// Provides a way to extend the <see cref="HtmlHelper" /> to construct objects of various kinds.
/// </summary>
public static class HtmlHelperExtensions
{
#region Grid
/// <summary>
/// Constructs a grid for a property that holds a collection.
/// </summary>
/// <typeparam name="TModel">The type of the model on which this grid is being build.</typeparam>
/// <typeparam name="TEntity">The type of a single item in the collection.</typeparam>
/// <param name="htmlHelper">The helper on which this method is executed.</param>
/// <param name="dataSource">The datasource on which the items are bound.</param>
/// <returns>An <see cref="IGridBuilder{TEntity}" /> that is used to construct the grid.</returns>
public static IGridBuilder<TEntity> GridFor<TModel, TEntity>(this HtmlHelper<TModel> htmlHelper,
IEnumerable<TEntity> dataSource)
{
return new GridBuilder<TEntity>(htmlHelper, dataSource);
}
#endregion
}
Then the next one is an implementation of the IGridBuilder interface:
/// <summary>
/// Provides an implemention of the <see cref="IGridBuilder{TModel}" /> that is used to construct the grid through a
/// fluent API.
/// </summary>
/// <typeparam name="TModel">The type of the model that the grid will hold.</typeparam>
public class GridBuilder<TModel> : IGridBuilder<TModel>
{
#region Constructors
/// <summary>
/// Creates a new instance of the <see cref="GridBuilder{TModel}" />.
/// </summary>
/// <param name="helper">The <see cref="HtmlHelper" /> that is used to construct the grid.</param>
/// <param name="dataSource">The collection of objects that will be bound to the grid.</param>
public GridBuilder(HtmlHelper helper, IEnumerable<TModel> dataSource)
{
htmlHelper = helper;
DataSource = dataSource;
Constructor = new GridConstructor<TModel>(htmlHelper, DataSource);
}
#endregion
#region IGridBuilder Members
/// <summary>
/// Gets the name of the <see cref="IGridBuilder{TModel}" />.
/// </summary>
public string Name { get; private set; }
/// <summary>
/// Gets the constructor that will be used to construct this <see cref="IGridBuilder{TModel}" />.
/// </summary>
public IGridContructor<TModel> Constructor { get; set; }
/// <summary>
/// Gets the source that will be bound to the implemented object.
/// </summary>
public IEnumerable<TModel> DataSource { get; private set; }
/// <summary>
/// Gets the <see cref="HtmlHelper" /> object.
/// </summary>
public HtmlHelper htmlHelper { get; private set; }
/// <summary>
/// Sets the name of the <see cref="IGridBuilder{TModel}" />. This name will be used as an id on the outer element that
/// holds the entire grid.
/// </summary>
/// <param name="name">The name that the <see cref="IGridBuilder{TModel}" /> should have.</param>
/// <returns>An <see cref="IGridBuilder{TModel}" /> that can be used to construct the grid through a fluent API.</returns>
public IGridBuilder<TModel> WithName(string name)
{
Name = name;
return this;
}
/// <summary>
/// Set the columns of the model that should be bound to grid.
/// </summary>
/// <param name="bindAllColumns">The action that will bind all the columns.</param>
/// <returns>An <see cref="IGridBuilder{TModel}" /> that is used to construct the grid.</returns>
public IGridBuilder<TModel> WithColumns(Action<IColumnBinder<TModel>> bindAllColumns)
{
var columnBinder = new ColumnBinder<TModel>(Constructor);
bindAllColumns(columnBinder);
return this;
}
/// <summary>
/// Renders the grid with all the set properties.
/// </summary>
/// <returns>A <see cref="MvcHtmlString" /> that contains the HTML representation of the grid.</returns>
public MvcHtmlString Render()
{
var outputBuilder = new StringBuilder();
BaseElementBuilder parentElement = DivFactory.DivElement().WithCss("header");
outputBuilder.Append(parentElement.ToString(TagRenderMode.StartTag));
outputBuilder.Append(parentElement.ToString(TagRenderMode.EndTag));
return new MvcHtmlString(outputBuilder.ToString());
}
#endregion
}
Then an implementation of the IGridColumnBinder:
/// <summary>
/// Provides an implementation of the <see cref="IColumnBinder{TModel}" /> that can be used to construct a column
/// through a fluent API.
/// </summary>
/// <typeparam name="TModel">The type of the datasource that's bound to the grid.</typeparam>
public class ColumnBinder<TModel> : IColumnBinder<TModel>
{
#region Constructors
/// <summary>
/// Creates a new instance of the <see cref="ColumnBinder{TModel}" />.
/// </summary>
/// <param name="constructor">An <see cref="IGridContructor{TModel}" /> that contains the builder to construct the grid.</param>
public ColumnBinder(IGridContructor<TModel> constructor)
{
Constructor = constructor;
}
#endregion
#region IColumnBinder Members
/// <summary>
/// Gets the values that are bound to this <see cref="IColumnBinder{TModel}" />.
/// </summary>
public IGridContructor<TModel> Constructor { get; private set; }
/// <summary>
/// Gets the css class of the <see cref="IColumnBinder{TModel}" />.
/// </summary>
public string CssClass { get; private set; }
/// <summary>
/// Gets the values that are bound to this <see cref="IColumnBinder{TModel}" />.
/// </summary>
public IList<object> Values { get; set; }
/// <summary>
/// Binds an column to the grid.
/// </summary>
/// <typeparam name="TItem">The type of the column on which to bind the items.</typeparam>
/// <param name="propertySelector">The functional that will bind the control to the grid.</param>
/// <returns>As <see cref="IColumnBinder{TModel}" /> that is used to construct this column through a fluent API.</returns>
public IColumnBinder<TModel> Bind<TItem>(Expression<Func<TModel, TItem>> propertySelector)
{
string name = ExpressionHelper.GetExpressionText(propertySelector);
name = Constructor.htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForProperty(() => default(TModel),
typeof (TModel), name);
// Get's the name to display on the column in grid. The Display attribute is used if present, otherwise the name of the property is used.
string displayName = string.IsNullOrEmpty(metadata.DisplayName)
? metadata.PropertyName
: metadata.DisplayName;
Values =
Constructor.DataSource.Select(myVar => propertySelector.Compile()(myVar))
.Select(dummy => (object) dummy)
.ToList();
Constructor.builderProperties.Add(displayName, this);
return this;
}
/// <summary>
/// Apply a specific css class on an element.
/// </summary>
/// <param name="className">The name of the css class that should be placed on the element.</param>
/// <returns>As <see cref="IColumnBinder{TModel}" /> that is used to construct this column through a fluent API.</returns>
public IColumnBinder<TModel> WithCss(string className)
{
CssClass = className;
return this;
}
#endregion
}
And as last the implementation of the IGridConstructor.
/// <summary>
/// Provides an implemention of the <see cref="IGridContructor{TModel}" /> that is used to construct the grid through a
/// fluent API.
/// </summary>
/// <typeparam name="TModel">The type of the model that the grid will hold.</typeparam>
public class GridConstructor<TModel> : IGridContructor<TModel>
{
#region Constructors
/// <summary>
/// Creates a new instance of the <see cref="GridConstructor{TModel}" />.
/// </summary>
/// <param name="helper">The <see cref="HtmlHelper" /> that is used to built the model.</param>
/// <param name="source">The model that is bound to the grid.</param>
public GridConstructor(HtmlHelper helper, IEnumerable<TModel> source)
{
htmlHelper = helper;
DataSource = source;
builderProperties = new Dictionary<string, IColumnBinder<TModel>>();
}
#endregion
#region Properties
/// <summary>
/// Provides a dictionary that contains all the properties for the builder.
/// </summary>
public IDictionary<string, IColumnBinder<TModel>> builderProperties { get; set; }
/// <summary>
/// Gets the source that will be bound to the implemented object.
/// </summary>
public IEnumerable<TModel> DataSource { get; private set; }
/// <summary>
/// Gets the <see cref="HtmlHelper" /> object.
/// </summary>
public HtmlHelper htmlHelper { get; private set; }
#endregion
}
Now, how does this works exactely?
The HtmlHelper returns an member that implements an IGridBuilder, so in the example above, it returns a GridBuilder.
On that GridBuilder, there are a couple of elements that you can call, and one more important is the WithColumns method that takes a IColumnBinder action and there's the trick. The implementation of IColumnBinder takes a reference to an IGridConstructor. And it's that constructor that will be fully built up.
So all the things we need to know for rendering, including each css class for a given column are exposed through the GridBuilder.GridContructor
So, a very vert long post, but I hope it helps some people.

Can I refresh an XML comment in Visual Studio to reflect parameters that have changed?

If I write the function:
public static uint FindAUint(double firstParam)
{
}
I can generate the xml comments by typing '///', it gives :
/// <summary>
/// *Here I type the summary of the method*
/// </summary>
/// <param name="firstParam">*Summary of param*</param>
/// <returns>*Summary of return*</returns>
public static uint FindAUint(double firstParam)
{
}
If I then decide I need to update my method to be:
/// <summary>
/// *Here I type the summary of the method*
/// </summary>
/// <param name="firstParam">*Summary of param*</param>
/// <returns>*Summary of return*</returns>
public static uint FindAUint(double firstParam,double newParam, double newParam2)
{
}
Is there a way to get visual studio to add the new params into the xml without losing the descriptions of the previous ones?
(I should mention I am using Visual Studio Express; I wouldn't put it past Microsoft to disallow the feature in the Express version though)
Check out GhostDoc. It is a Visual Studio extension that will generate your XML comments for you.
ReSharper works very nice for me; it warns whenever the XML comment does not match a method's signature.
Also, using the ALT + ENTER keyboard shortcut, ReSharper can fix these mismatches by adding/removing the necessary XML comments.
A workaround is to select the current block of XML Documentation and to comment it out. Then create a new line under the commented out code. A new XML Documentation block will be created with all the new values and you can copy paste your old values.
Example:
/// <summary>
/// Does something
/// </summary>
/// <param name="bar">True if not false</param>
/// <returns>Some really important value</returns>
public bool Foo(bool bar) {
return bar;
}
Changes to method
/// <summary>
/// Does something
/// </summary>
/// <param name="bar">True if not false</param>
/// <returns>Some really important name</returns>
public string Foo(bool bar, string bar2, int bar3) {
if (bar) {
return bar2 + bar3.ToString();
} else {
return "foobar";
}
}
Comment out the documentation
///// <summary>
///// Does something
///// </summary>
///// <param name="bar">True if not false</param>
///// <returns>Some really important name</returns>
public string Foo(bool bar, string bar2, int bar3) {
if (bar) {
return bar2 + bar3.ToString();
} else {
return "foobar";
}
}
In a new line under the commented out code enter /// to get the generated XML Documentation.
///// <summary>
///// Does something
///// </summary>
///// <param name="bar">True if not false</param>
///// <returns>Some really important value</returns>
/// <summary>
///
/// </summary>
/// <param name="bar"></param>
/// <param name="bar2"></param>
/// <param name="bar3"></param>
/// <returns></returns>
public string Foo(bool bar, string bar2, int bar3) {
if (bar) {
return bar2 + bar3.ToString();
} else {
return "foobar";
}
}

Categories