Hangfire.Console icon indicating copy to clipboard operation
Hangfire.Console copied to clipboard

Replace or extend the IProgressBar interface to use IProgress<T>

Open Turnerj opened this issue 5 years ago • 4 comments

There is a standard progress interface in .NET called IProgress<T> which, while a method signature is different, covers the existing interface's type of functionality.

It is easier to use this interface as it doesn't require the Hangfire.Console dependency across all libraries in a code base that need to provide progress.

I do understand a reluctance to fully replace IProgressBar as it would be a breaking change as well as IProgressBar allows int and double for values. What might be a fair middle ground (though still breaking) is to have IProgressBar extend both IProgress<int> and IProgress<double>.

Turnerj avatar Jul 13 '19 05:07 Turnerj

I have the following class to solve this issue:

public static class ProgressBarExtensionMethods
{
    public static IProgress<T> AsIProgress<T>(this IProgressBar progressBar, Func<T, double> convert)
    {
        return new ProgressConverter<T>(progressBar, convert);
    }

    private class ProgressConverter<T> : IProgress<T>
    {
        IProgressBar progressBar;
        Func<T, double> convert;
        public ProgressConverter(IProgressBar progressBar, Func<T, double> convert)
        {
            this.progressBar = progressBar;
            this.convert = convert;
        }

        public void Report(T value)
        {
            progressBar.SetValue(convert(value));
        }
    }
}

When using FluentFtp i can just do this:

var progress = context.WriteProgressBar().AsIProgress<FtpProgress>(x => x.Progress);
await client.UploadFileAsync(sourcePath, destinationPath, FtpExists.Overwrite, progress: progress, token: cancellationToken).ConfigureAwait(false);

Works great!

Peter-Optiway avatar Sep 27 '19 14:09 Peter-Optiway

Thanks @Peter-Optiway - I might use something similar to that in my project though would still be nice to have IProgressBar<> built-into the library itself. I'd be happy to write that PR though I don't know if the maintainer would accept that change.

Turnerj avatar Sep 28 '19 03:09 Turnerj

Indeed, I’ve mistakenly thought that interface was not available for old .NET Classic frameworks.

I‘m thinking of adding a new IProgressBar<T> interface extending both IProgressBar and IProgress<T>, and introducing IProgress<T> WriteProgressBar<T>(Func<T, double> converter) extension method. Would that fit your use cases?

I’m a bit busy with other projects at the moment though, so don’t expect it sometime soon. Sorry.

pieceofsummer avatar Dec 03 '19 15:12 pieceofsummer

Yeah, a method that returns an IProgress<T> is a good start. Ideally if there was one that already returned a IProgress<double> without a conversion function would be best.

I think it might be a good time to deprecate the current interface and return IProgressBar<double> instead. Internally you are already casting from int to a double.

Turnerj avatar Dec 04 '19 01:12 Turnerj