Automatically update method signature (for ex. summary comments)

Viewed 43

I'm looking for a way to automatically match the signature of a method between an interface, an abstract class and a derived class. It's really painful when I change one of the comments, to manually update it 3 times, because I have to update it in the interface, the abstract class and the derived class.. Is there a VS extension or something that could help me do that automatically? Btw, I'm using ReSharper Ultimate. Not sure if it has a such extension.

public interface IBotClient
{
    /// <summary>
    /// Gets account balance for an asset.
    /// </summary>
    /// <param name="asset">The asset.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balance.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    Task<Balance> GetBalanceAsync(string asset, CancellationToken ct = default);

    /// <summary>
    /// Gets account balances.
    /// </summary>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balances.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    Task<IList<Balance>> GetBalancesAsync(CancellationToken ct = default);

    ...
}

public abstract class BotClientBase : IBotClient
{
    private readonly IBinanceClient _client;
    private readonly IBinanceSocketClient _socketClient;

    protected BotClientBase(IBinanceClient client, IBinanceSocketClient socketClient)
    {
        _client = client;
        _socketClient = socketClient;
    }

    /// <summary>
    /// Gets account balance for an asset.
    /// </summary>
    /// <param name="asset">The asset.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balance.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    public abstract Task<Balance> GetBalanceAsync(string asset, CancellationToken ct = default);

    /// <summary>
    /// Gets account balances.
    /// </summary>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balances.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    public abstract Task<IList<Balance>> GetBalancesAsync(CancellationToken ct = default);

    ...
}

public class SpotBotClient : BotClientBase
{
    private readonly ILogger<SpotBotClient> _logger;
    private readonly IBinanceClient _client;
    private readonly IBinanceSocketClient _socketClient;

    public SpotBotClient(ILogger<SpotBotClient> logger, IBinanceClient client, IBinanceSocketClient socketClient) : base(client, socketClient)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _client = client;
        _socketClient = socketClient;
    }

    /// <summary>
    /// Gets account balance for an asset.
    /// </summary>
    /// <param name="asset">The asset.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balance.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    public override async Task<Balance> GetBalanceAsync(string asset, CancellationToken ct = default)
    {
        ...
    }

    /// <summary>
    /// Gets account balances.
    /// </summary>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balances.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    public override async Task<IList<Balance>> GetBalancesAsync(CancellationToken ct = default)
    {
        ...
    }

    ...
}
2 Answers

Documentation comments in C# allows you to use the <inheritdoc> tag, to automatically let derived types reuse the documentation comments from higher up in the hierarchy:

public interface IBotClient
{
    /// <summary>
    /// Gets account balance for an asset.
    /// </summary>
    /// <param name="asset">The asset.</param>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balance.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    Task<Balance> GetBalanceAsync(string asset, CancellationToken ct = default);

    /// <summary>
    /// Gets account balances.
    /// </summary>
    /// <param name="ct">Cancellation token.</param>
    /// <returns>The account balances.</returns>
    /// <exception cref="T:ElonMuskBot.Core.Exceptions.CallFailedException">If the call fails.</exception>
    Task<IList<Balance>> GetBalancesAsync(CancellationToken ct = default);

    ...
}

///<inheritdoc cref="IBotClient"/>
public abstract class BotClientBase : IBotClient
{
    
}

///<inheritdoc/>
public class SpotBotClient : BotClientBase
{
    
}

I found out that ReSharper had it built-in.

Alt+Enter on the overriden method and then "Copy documentation from base".

Related