【问题标题】:generic extension method on IQueryable<T> [duplicate]IQueryable<T> 上的通用扩展方法 [重复]
【发布时间】:2013-06-17 04:11:42
【问题描述】:

我在 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());
}

现在,鉴于strLinqResultIQueryable&lt;string&gt;,我需要将其命名为strLinqResult.Bar&lt;int,string&gt;();

重点是我必须传递这两种类型,即使第一种类型已经知道,因为我正在调用已经定义的IQuerable 上的方法。

既然调用 Foo(2)not Foo&lt;string&gt;(2) 就足够了,我认为编译器能够自动“传递/猜测”类型。

那么为什么我需要调用第二种方法Bar&lt;int,string&gt;(); 而不仅仅是Bar&lt;int&gt;()


实际代码:

    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 对象中可用的分页和排序参数。

Itemspublic List&lt;T&gt; Items 中的 class ListResponse&lt;T&gt;

TranslateTo 是 ServiceStack 中的一个方法。

上面调用 NHibernate(T 是域模型)返回的 IQueryable&lt;T&gt; 的方法获取请求参数(排序、分页),应用它们,然后将结果列表从 DomainModel 转换为类型为 @987654343 的 DTO 对象@。然后将该列表包装在一个通用响应类中(通用,因此它可用于许多 DTO 类型)

【问题讨论】:

  • 您是否尝试过将定义切换为Bar&lt;TSource, TTarget&gt;(...)
  • @PinnyM 是的,我做到了。它仍然说我需要传递 2 个类型参数
  • @Jon 我可能误解了其他解决方案,但扩展实际类是不可能的 - 它需要是扩展方法!
  • @migajek:链接的答案建议在单独的泛型类(不是您正在使用的类)上使用静态方法。或者,您可以安排使用中间类型使用扩展方法语法进行调用,但这需要 两个 扩展方法调用。仅通过一次调用使用扩展方法语法要求编译器仅推断类型参数之一,而它不会这样做。
  • 假设您添加了Bar&lt;TSource&gt;(this IEnumerable&lt;TSource&gt; source)。如果编译器接受了您的速记,那么现在strLinqResult.Bar&lt;string&gt;(); 是指Bar&lt;string&gt; 还是Bar&lt;string, string&gt; 将是明确的。我认为这就是 Johny Skovdal 在他的回答中的意思,但我想把它拼出来。

标签: c# generics extension-methods


【解决方案1】:

如果我对您的问题的理解正确,那么您就是在尝试输入尽可能少的参数。那是不可能的。它可以自己解决所有问题,也可以全部解决。

只指定一些的问题在于,您将能够引入一个类型参数少 1 个的类似方法,并且现在会破坏实现。

但是你有没有机会分享你原来的问题呢?或许可以让编译器以其他方式解决?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2010-10-26
    • 2011-07-28
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多