我已经在IQueryable上编写了一个扩展方法,它返回相同类型的IQueryable,只是进行了一些过滤。假设它是这样的:
public static IEnumerable<T> Foo<T>(this IEnumerable<T> source, int? howmany = null)
{
if (howmany.HasValue)
return source.Take(howmany.Value);
return source;
}
调用上述方法就像这样简单:
someLinqResult.Foo(2)
我需要另一个方法,它将返回其他基类不同于源T
的其他泛型类的实例。因此,这里是代码,假设该方法应该返回给定类型的列表(与IQueryable具有不同的输入类型!)但长度相同[实际问题是关于转换NHibernate查询结果,但这并不重要]:
public static List<TTarget> Bar<TTarget,TSource>(this IEnumerable<TSource> source)
{
return new List<TTarget>(source.Count());
}
现在,考虑到strLinqResult
是IQueryable<string>
,我需要调用它的strLinqResult.Bar<int,string>();
。
关键是我必须传递两种类型,即使第一种类型已经知道,因为我正在已定义的IQuerable
上调用方法。
由于只需调用Foo(2)
而不是Foo<string>(2)
,我认为编译器能够自动“传递/猜测”类型。
那么为什么我需要调用第二个方法Bar<int,string>();
而不仅仅是Bar<int>()
?
实际代码:
public static ListResponse<TResponse>
BuildListResponse<T,TResponse>(this IQueryable<T> iq, ListRequest request)
where TResponse: new()
{
var result = iq.ApplyListRequestParams(request).ToList().ConvertAll(x => x.TranslateTo<TResponse>());
var tcount = iq.Count();
return new ListResponse<TResponse> {
Items = result,
_TotalCount = tcount,
_PageNumber = request._PageNumber ?? 1,
};
}
ApplyListRequestParams
是示例代码中的一种Foo
方法 - 它仅适用于ListRequest
对象中可用的分页和排序参数。
Items
是ListResponse<T>
类中的一个public List<T> Items
。
TranslateTo
是ServiceStack中的一个方法。上述方法在NHibernate返回的
IQueryable<T>
(T是域模型)上调用,它采用请求参数(排序、分页),应用它们,然后将结果列表从DomainModel
转换为类型为TResponse
的DTO对象。然后,该列表被包装在一个泛型响应类中(泛型,因此它可重复使用于多个DTO类型)。
Bar<TSource>(this IEnumerable<TSource> source)
。如果编译器接受了您的速记方式,那么现在strLinqResult.Bar<string>();
是指Bar<string>
还是Bar<string, string>
就不再含糊不清了。我认为这就是 Johny Skovdal 在他的回答中所说的,但我想详细说明一下。 - Tim Goodman