Sto scrivendo un PCL che utilizza HttpClient
per visitare alcuni siti ed estrarre i dati da essi. Il mio codice iniziale assomigliava a questo:
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());
}
}
}
Mi sono reso conto, tuttavia, che questo sarebbe uno spreco di risorse se l'utente della mia libreria già avesse un HttpClient
in mano. Ad esempio:
// Caller code
using (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
}
Una soluzione potrebbe essere quella di aggiungere un overload prendendo un HttpClient
come parametro, ma cosa succede se l'utente volesse usare WebClient
invece? O un HttpWebRequest
? O qualche altro tipo di client che non era disponibile nel PCL?
La mia soluzione
Ho deciso di prendere i parametri delegati per ottenere l'origine della pagina e per scaricare il file basato sull'URI. Il mio codice ora appare così:
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());
}
}
Il problema
Hm. Aspetta, e se il chiamante utilizza un client che non supporta async
, come HttpWebRequest
? È meglio aggiungere un altro sovraccarico prendendo un Func<string>
e un Func<string, byte[]>
. Cosa fare se si desidera effettuare la prima chiamata sincrona, ma la seconda chiamata async
? O vice versa? OK, aggiungi solo 2 più sovraccarichi. Aspetta, e se il chiamante vuole che l'intera operazione sia sincrona? Andiamo ad aggiungere 4 Download.FromYouTube
overload avvolgendo ciascuno dei metodi async
. Spero che sia necessario visitare la pagina un'altra di YouTube nel caso in cui la firma del video sia crittografata! Certo, andiamo ad aggiungere 8 mor -
Penso che tu possa vedere dove sta andando. Come faccio a mantenere questa flessibilità senza spaventare l'utente quando Visual Studio dice che ci sono 17 diversi overload per questo metodo?