I'm writing a PCL that uses an HttpClient to go visit a few sites and extract data from them. My initial code looked like this:public static class Download{    public async static Task<byte[]> FromYouTubeAsync(string videoUri)    {        using (var client = new HttpClient())        {            string source = await client                .GetStringAsync(videoUri);            // get links...            return await client                .GetByteArrayAsync(links.First());        }    }}I realized, however, that this would be a waste of resources if the user of my library already had a HttpClient in hand. For example:// Caller codeusing (var client = new HttpClient()){    // Do some work with client    byte[] bytes = await Download.FromYouTubeAsync(some://uri); // A second HttpClient is created here, wasting resources and time...    // Do some work with client and bytes}One solution could be to add an overload taking an HttpClient as a parameter, but what if the user wanted to use a WebClient instead? Or an HttpWebRequest? Or some other kind of client that wasn't availsble in the PCL?My solutionI decided to take delegate parameters to get the page source and to download the file based on the URI. My code now looks like this:public static class Download{    public async static Task<byte[]> FromYouTubeAsync(string videoUri)    {        using (var client = new HttpClient())        {            return await FromYouTubeAsync(                () => client                .GetStringAsync(videoUri),                uri => client                .GetByteArrayAsync(uri));        }    }    public async static Task<byte[]> FromYouTubeAsync(        Func<Task<string>> sourceFactory, Func<string, Task<byte[]>> downloadFactory)    {        string source = await sourceFactory();        // get links...        return await downloadFactory(links.First());    }}The problemHm. Wait, what if the caller is using a client that doesn't support async, like HttpWebRequest? Better add another overload taking a Func<string> and a Func<string, byte[]>. What if s/he wants to make the first call synchronous, but the second call async? Or vice versa? OK, just add 2 more overloads. Wait, what if the caller wants the whole operation to be synchronous? Let's go add 4 Download.FromYouTube overloads wrapping each of the async methods. Whoops, it turns out we need to visit another page of YouTube in case the video's signature is encrypted! Sure, let's go add 8 mor-I think you can see where this is going. How do I maintain this flexibility without scaring the user away when Visual Studio says that there are 17 different overloads for this method?
Using delegates to avoid duplicate creation of resources
c#;design patterns;functional programming;library;delegates