作爲一個業餘愛好項目(並將自己更深入的泛型/擴展方法),我正在寫一個參數檢查庫!當類型參數爲IEnumerable <T>時,如何將擴展方法附加到泛型類?
我有一個模型叫參數描述參數,看起來像這樣:
public class Argument<T>
{
internal Argument(string name, T value)
{
Name = name;
Value = value;
}
public string Name { get; private set; }
public T Value { get; private set; }
}
在參數驗證開始,該對象的實例被創建,以及個人驗證通過調用擴展方法進行(包含實際的邏輯),掛起它。
一個這樣的擴展方法驗證集合包含至少一個項目,目前看起來是這樣的:
public static Argument<IEnumerable<T>> HasItems<T>(this Argument<IEnumerable<T>> argument)
{
if (!argument.Value.Any())
throw Error.Generic(argument.Name, "Collection contains no items.");
return argument;
}
但它似乎沒有工作。如果是我,說,寫這個單元測試:
[TestMethod]
public void TestMethod1()
{
var argument = new List<int>() { 1, 2, 6, 3, -1, 5, 0 };
Validate.Argument("argument", argument)
.IsNotNull()
.HasItems()
.All(v => v.IsGreaterThan(0));
}
HasItems不會在智能感知顯示,和我得到這個編譯錯誤:
'Validation.Argument<System.Collections.Generic.List<int>>'
does not contain a definition for 'HasItems' and no extension method 'HasItems' accepting a first argument of type'Validation.Argument<System.Collections.Generic.List<int>>'
could be found (are you missing a using directive or an assembly reference?)
如果我嘗試傳遞直接進入價值擴展方法,像這樣:
CollectionTypeExtensions.HasItems(Validate.Argument("argument", argument));
我得到這個:
The best overloaded method match for
'Validation.CollectionTypeExtensions.HasItems<int>(Validation.Argument<System.Collections.Generic.IEnumerable<int>>)'
has some invalid arguments
根據我的研究,我會需要這個工作被稱爲「變異」,並適用於接口和委託,而不是類(即:所有的類都是不變)
那說,它可能以另一種方式工作。一個想到的是重寫它直奔T,像這樣:
public static Argument<T> HasItems<T, TElement>(this Argument<T> argument)
where T : IEnumerable<TElement>
{
if (!argument.Value.Any())
throw Error.Generic(argument.Name, "Collection contains no items.");
return argument;
}
..但不工作,要麼因爲它需要TElement明確指定調用方法時。我也可以回到在類型約束中使用非泛型IEnumerable接口,但是我必須找到一種方法將IEnumerable強制爲IEnumerable(這需要知道T在這個上下文中),或者重複Any()爲了測試是否存在任何項目的功能,和還有另一個擴展方法(全部),這將是非常非常混亂的,所以我寧願避免它。
所以最終,我想我的問題是:如何讓我的擴展方法正確連接?
那......確實工作!當我今天早上用新鮮的眼睛看這個時,我最終走了一條不同的路線,但我標記爲答案,因爲它簡潔地解決了所提出的問題。謝謝! – 2013-03-03 19:43:18