作为一个业余爱好项目(并将自己更深入的泛型/扩展方法),我正在写一个参数检查库!当类型参数为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