Was Sie verlangen, ist effektiv ein discriminated union. C# hat eigentlich nicht so etwas. Es gibt ein paar Möglichkeiten, dies zu umgehen. Zunächst betrachten, was ich als das try/out Muster:
public bool GetAllResults(string token, string username, out List<AllReportVM> results);
Das ist in Ordnung für relativ einfache Methoden, aber es nicht wirklich geben Sie die Fehlermeldung (zumindest angesichts der Art und Weise sie in der Regel umgesetzt wird) und out
Parameter funktionieren nicht mit async
Methoden. Also können wir das ausschließen.
Die zweite Möglichkeit besteht darin, throw an exception auf einen Fehler, und das, was würde ich in 90% der Situationen empfehlen:
public async Task<List<AllReportVM>> GetAllReports(string token, string username)
{
var httpClient = GetHttpClient();
if (CrossConnectivity.Current.IsConnected) {
var response = await httpClient.GetAsync ("getdashboardreports.ashx").ConfigureAwait (false);
if (response.IsSuccessStatusCode) {
var content = response.Content;
string jsonString = await content.ReadAsStringAsync().ConfigureAwait (false);
return JsonConvert.DeserializeObject<List<AllReportVM>> (jsonString);
} else {
throw new RequestException("SystemError");
}
} else {
throw new RequestException("Internet Connectivity Error");
}
}
Und das nennen würden Sie verwenden müssen:
try
{
var list = await obj.GetAllReports(token, username);
...
}
catch (RequestException ex)
{
Console.WriteLine(ex.Message);
}
Dies ist ein ziemlich solides, gut etabliertes Muster. Tatsächlich sollten Sie die Ausnahmebehandlung wahrscheinlich bereits für alle möglichen anderen Ausnahmen verwenden, die möglicherweise in Ihrer Anwendung auftreten. Es hat jedoch einige Auswirkungen auf die Leistung und Sie sollten Ausnahmen für den einfachen Kontrollfluss vermeiden. Dies ist möglicherweise keine Option für Anwendungen, die viele Anfragen stellen müssen und von denen erwartet wird, dass sie Fehler effizient behandeln (z. B. Stapelverarbeitung). Wenn ich Situationen wie dies in der Vergangenheit erlebt habe, habe ich es nützlich finde eine benutzerdefinierte Klasse zu implementieren, zum Beispiel:
public class RequestResult<T>
{
public bool Success { get; }
public T Result { get; }
public string ErrorMessage { get; }
private RequestResult(bool success, T result, string errorMessage)
{
this.Success = success;
this.Result = result;
this.ErrorMessage = errorMessage;
}
public static RequestResult<T> Success(T result)
{
return new RequestResult<T>(true, result, null);
}
public static RequestResult<T> Failure(string errorMessage)
{
return new RequestResult<T>(false, default(T), errorMessage);
}
}
public async Task<RequestResult<List<AllReportVM>>> GetAllReports(string token, string username)
{
var httpClient = GetHttpClient();
if (CrossConnectivity.Current.IsConnected) {
var response = await httpClient.GetAsync ("getdashboardreports.ashx").ConfigureAwait (false);
if (response.IsSuccessStatusCode) {
var content = response.Content;
string jsonString = await content.ReadAsStringAsync().ConfigureAwait (false);
var result = JsonConvert.DeserializeObject<List<AllReportVM>> (jsonString);
return RequestResult.Success(result);
} else {
return RequestResult.Failure("SystemError");
}
} else {
return RequestResult.Failure("Internet Connectivity Error");
}
}
haben Sie versucht, mit Generika Typ –
Nein, das können Sie nicht tun. Wenn ein Client sagt "ServerData data = erwarten GetAllReports();", muss der Compiler wissen, dass 'ServerData' der richtige Rückgabetyp ist. Der Compiler kann nicht wissen, ob die Anfrage zur Laufzeit erfolgreich ist oder fehlschlägt! Wenn ich Sie wäre, würde ich eine "Response" -Klasse machen, die alle zurückgegebenen Informationen enthält: Success boolean, ErrorMessage string, Result ServerData. Lassen Sie ErrorMessage einfach null, wenn kein Fehler, etc. * Edit * oder werfen Sie eine Ausnahme, natürlich. – Blorgbeard