Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

generic extension method on IQueryable<T> [duplicate]

I've written an extension method on IQueryable which returns the same type of IQueryable, just filtered a bit. Let's say it's something like that:

public static IEnumerable<T> Foo<T>(this IEnumerable<T> source, int? howmany = null)
{
    if (howmany.HasValue)
        return source.Take(howmany.Value);
    return source;
}

calling the above method is as simple as someLinqResult.Foo(2)

I need other method that will return instance of other generic class, but with other base class (not the same as source T above). So, here's the code, let's assume this method is supposed to return a list of given type (other than the input type which IQueryable has!) but the same length [the actual problem is about transforming NHibernate query results, but it doesn't matter):

public static List<TTarget> Bar<TTarget,TSource>(this IEnumerable<TSource> source)
{
    return new List<TTarget>(source.Count());
}

now, given that the strLinqResult is IQueryable<string>, I need to call it strLinqResult.Bar<int,string>();.

The point is I have to pass both types, even though the first one is already known as I'm calling the method on already defined IQuerable.

Since it was enough to call Foo(2) and not Foo<string>(2) I thought the compiler is able to "pass/guess" the type automatically.

So why do I need to call the second method Bar<int,string>(); and not just Bar<int>() ?


the actual code:

    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 is kind of Foo method from the example code - it just applies pagination & ordering params available in ListRequest object.

Items is a public List<T> Items in a class ListResponse<T>.

TranslateTo is a method from ServiceStack.

The above method called on IQueryable<T> returned by NHibernate (T is Domain Model) takes the request parameters (ordering, pagination), applies them, and then transforms the results list from DomainModel to DTO Object of type TResponse. The list is then wrapped in a generic response class (generic, so it is reusable for many DTO types)

like image 836
migajek Avatar asked Jun 16 '13 19:06

migajek


1 Answers

If I'm understanding your problem correctly, you're attempting to input as few parameters as possible. That's just not possible. It's all or none where it can figure all out on its own.

The problem with only specifying some, is that you will the be able to introduce a similar method with the 1 less type parameter, and will now have broken the implementation.

But any chance you could share your original problem as well? Might be able to let the compiler figure it out some other way?

like image 121
Johny Skovdal Avatar answered Oct 06 '22 20:10

Johny Skovdal