2016-09-01 121 views
6

所以我創建了一個提供者(其中幾個實際),我意識到在我的一些邏輯中存在一些模式。它被重複,我想我可以刪除大量的代碼行,如果我可以創建這個擴展方法:d處理空值返回的靜態方法

所以,基本上所發生的事情是這樣的:

// Get our item to be deleted 
var model = await this._service.GetAsync(id); 

// If we have nothing, throw an error 
if (model == null) 
    throw new HttpException(404, string.Format(Resources.GenericNotFound, "List item")); 

現在,我在很多地方做這個,不只是爲了刪除,而是爲了更新。 我想創建一個擴展方法,它允許我做這樣的事情:

// Get our item to be deleted 
var model = await this._service.GetAsync(id).ThowIfNull("List item"); 

我還需要這與任何返回類型的工作。所以在這種情況下,它可能是帳戶,但會有一個提供商也有此代碼返回訂單但我需要擴展方法爲兩個工作。

我認爲這裏的挑戰是異步,但我可能是錯的!

任何人都知道是否有可能?

+0

那麼一種可能是'(等待this._wervice.GetAsync(ID))。ThrowIfNull(「List item」);'如果你想在任何'model'上使用擴展方法(或者甚至可以在'object'上)而不是'Task ' – juharr

+0

你能寫這個例子嗎? – r3plica

回答

5

一種可能性,以避免異步等待部分是使該類型的擴展方法工作返回Task

public static T ThrowIfNull<T>(this T obj, string message) where T : class 
{ 
    if (obj == null) 
     throw new HttpException(404, string.Format(Resources.GenericNotFound, message)); 
    return obj; 
} 

裏面我做了擴展方法一般,因爲我不知道model是什麼類型。然後你可以像這樣使用它。

var model = (await this._service.GetAsync(id)).ThrowIfNull("List item"); 

通過將await在括號中你要確保它會等待的任務,並將結果傳遞給擴展方法之前解開它。

另一種選擇將是使上Task<T>

public static async Task<T> ThrowIfNullAsync<T>(this Task<T> task, string message) 
where T : class 
{ 
    var obj = await task; 
    if (obj == null) 
     throw new HttpException(404, string.Format(Resources.GenericNotFound, message)); 
    return obj; 
} 

進一步擴展方法的工作,你不需要括號。

var model = await this._service.GetAsync(id).ThrowIfNullAsync("List item"); 

但是這意味着異常現在被包裝在任務中,根據您如何使用此方法,可能會或可能不會取得滿意的結果。

+0

您不需要讓它們具有不同的名稱,只需讓它們使用相同的名稱並相互重載即可,這與'Task.Run'工作方式相同。這樣你就可以在同步和異步方法上使用'ThrowIfNull'。 –

+0

@ScottChamberlain確實如此,但我個人以不同的方式訂閱了異步方法的命名原則。 – juharr

+0

我也是juharr,感謝這:) – r3plica

3

您可以定義任何T擴展方法:

public static class GenericExtensions 
{ 
    public static T ThrowIfNull<T>(this T obj, string message) 
    { 
     if (obj == null) 
      throw new HttpException(404, 
       string.Format(Resources.GenericNotFound, message)); 
     return obj; 
    } 
} 

如果你不關心你可以使用object返回類型,但會招致拳擊值類型(不知道我會實際使用此):

public static class ObjectExtensions 
{ 
    public static void ThrowIfNull(this object obj, string message) 
    { 
     if (obj == null) throw new ArgumentNullException(message); 
    } 
} 

,然後用它在任何返回類型:

async Task SomeAsyncMethod() 
{ 
    (await Foo()).ThrowIfNull("hello"); 
} 

public Task<int> Foo() 
{ 
    return Task.FromResult(0); 
} 
0

我創造了這樣的方法:

/// <summary> 
/// Throws a 404 Not found exception 
/// </summary> 
/// <param name="model">The model to check</param> 
/// <param name="name">The name to display in the message</param> 
/// <returns></returns> 
public static T ThrowIfNotFound<T>(this T model, string name) 
{ 

    // If we have nothing, throw an error 
    if (model == null) 
     throw new HttpException(404, string.Format(Resources.GenericNotFound, name)); 

    // Return our model 
    return model; 
}